1002: [FJOI2007]轮状病毒
Description
轮状病毒有很多变种,所有轮状病毒的变种都是从一个轮状基产生的。一个N轮状基由圆环上N个不同的基原子
和圆心处一个核原子构成的,2个原子之间的边表示这2个原子之间的信息通道。如下图所示
N轮状病毒的产生规律是在一个N轮状基中删去若干条边,使得各原子之间有唯一的信息通道,例如共有16个不
同的3轮状病毒,如下图所示
现给定n(N<=100),编程计算有多少个不同的n轮状病毒
Input
第一行有1个正整数n
Output
计算出的不同的n轮状病毒数输出
Sample Input
3
Sample Output
16
//一开始非常nb地推了个组合数的公式,但是要写高精阶乘 高精除高精,就没写 //然后就写longlong看看能过几个点 //A掉一个点,和题解对了下,发现只有n<=3的时候是对的 //不会别的做法,看了题解。 //有矩阵树定理的做法和递推的做法 //感觉递推的比较好写,不用写高精乘法 //将n<=5的ans写出来,可以发现f[n]=3*f[n-1]-f[n-2]+2 //其实上面那个式子是个斐波那契的变形,整理一下可以得到这个式子 //不可避免地要写高精 #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; int n; int ans[105][1005]; int len[105]; int mul[1005]; void calc(int x) { int m=x-2,n=x-1; int cnt=0;int l=len[n]; for(int i=1;i<=l;++i) { mul[i]=(3*ans[n][i]+cnt)%10; cnt=(3*ans[n][i]+cnt)/10; } if(cnt) mul[++l]=cnt; cnt=2; for(int i=1;i<=l;++i) { ans[x][i]=(mul[i]-ans[m][i]+cnt+10)%10; if(mul[i]-ans[m][i]+cnt<0) cnt=-1; else cnt=(mul[i]-ans[m][i]+cnt)/10; } if(cnt) ans[x][l+1]=cnt,len[x]=l+1; else len[x]=l; return; } int main() { scanf("%d",&n); ans[1][1]=1,len[1]=1; ans[2][1]=5,len[2]=1; for(int i=3;i<=n;++i) calc(i); for(int i=len[n];i;--i) cout<<ans[n][i]; return 0; }