poj 1737男人八题之一 orz ltc
這是樓教主的男人八題之一。很高興我能做八分之一的男人了。
題目大意:求有n個頂點的連通圖有多少個。
解法:
1、? 用總數減去不聯通的圖(網上說可以,我覺得時間懸)
2、??? 用動態規劃(數學遞推)。網上講的方法我覺得非常難懂,但好像也沒有更好的表示。我就說一下吧:
用dp[i]表示i個頂點時的連通圖的總數。
考慮將1號點去除后,2號點所在的聯通塊。設此聯通塊有k個點,則這塊共有C(n-2,k-1)種取法。
回過頭來看剛開始的圖。可以把圖分成兩塊,一是上述聯通塊,其余的另一塊(此塊也一定聯通),這兩塊之間至少有一條連線,而這些線段肯定有一個頂點是1號點(用反證法很容易得到)。K個頂點連線到1號點的情況總共有2^k種,去除一種都不連的情況,還剩(2^k)-1種。故此時共有dp[j]*dp[i-j]*((2^k)-1)*C(n-2,k-1)
綜上,dp[i]=sigma{ dp[j]*dp[i-j]*((2^k)-1)*C(n-2,k-1)} (1<=j<i)
最后提醒一句,雖然大家都知道:要用高精度
代碼:
#include<cstdio>
#include<cstring>
using namespace std;
?
int max(int x,int y){
return(x>y)?x:y;
}
struct bign{
int len,p[240];
bign(){
?????????? len=1;
?????????? memset(p,0,sizeof(p));
}
bign operator =(const bign &o){
?????????? len=o.len;
?????????? memcpy(p,o.p,sizeof(p));
?????????? return *this;
}
bign operator +(const bign &o){
?????????? bign ans;
?????????? ans.len=max(len,o.len)+1;
?????????? int g=0;
?????????? for(int i=0;i<ans.len;i++){
??????????????????? int x=p[i]+o.p[i]+g;
??????????????????? ans.p[i]=x%10000;
??????????????????? g=x/10000;
?????????? }
?????????? if(ans.p[ans.len-1]==0)ans.len--;
?????????? return ans;
}
bign operator *(const bign &o){
?????????? bign ans;
?????????? ans.len=len+o.len;
?????????? for(int i=0;i<len;i++)
??????????????????? for(int j=0;j<o.len;j++){
???????????????????????????? ans.p[i+j]+=p[i]*o.p[j];
???????????????????????????? ans.p[i+j+1]+=ans.p[i+j]/10000;
???????????????????????????? ans.p[i+j]%=10000;
??????????????????? }
?????????? while(ans.p[ans.len-1]==0)ans.len--;
?????????? return ans;
}
void print(){
?????????? printf("%d",p[len-1]);
?????????? for(int i=len-2;i>=0;i--){
??????????????????? if(p[i]<10)printf("000%d",p[i]);
??????????????????? if(p[i]>=10 && p[i]<100)printf("00%d",p[i]);
??????????????????? if(p[i]>=100 && p[i]<1000)printf("0%d",p[i]);
??????????????????? if(p[i]>=1000 && p[i]<10000)printf("%d",p[i]);
?????????? }
?????????? printf("\n");
?????????? return;
}
}dp[51],tmp,c[51][51],two[51];
?
void init(bign &x){
x.len=1;
memset(x.p,0,sizeof(x.p));
x.p[0]=1;
return;
}
int main(){
int n;
scanf("%d",&n);
init(two[0]);
for(int i=1;i<=50;i++)
?????????? two[i]=two[i-1]+two[i-1];
for(int i=0;i<=50;i++)
?????????? two[i].p[0]--;
init(c[0][0]);
for(int i=1;i<=50;i++){
?????????? init(c[i][0]);init(c[i][i]);
?????????? for(int j=1;j<i;j++)
??????????????????? c[i][j]=c[i-1][j]+c[i-1][j-1];
}
init(dp[2]);init(dp[1]);
for(int i=3;i<=50;i++){
?????????? for(int j=1;j<i;j++)
??????????????????? dp[i]=dp[i]+dp[j]*dp[i-j]*two[j]*c[i-2][j-1];
}
while(n!=0){
?????????? dp[n].print();
?????????? scanf("%d",&n);
}
return 0;
}
轉載于:https://www.cnblogs.com/shanquan2/p/3176382.html
總結
以上是生活随笔為你收集整理的poj 1737男人八题之一 orz ltc的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: poj 3469 Dual Core C
- 下一篇: 前端性能优化:使用媒体查询加载指定大小的