bzoj1002 [FJOI2007]轮状病毒——找规律+高精度
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1002
打表找规律,似乎是这样:https://blog.csdn.net/fzhvampire/article/details/46389897
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n; struct N{ int a[50005]; N(){memset(a,0,sizeof a);} }f[105],ans; N add(N x,N y) { N ret; ret.a[0]=max(x.a[0],y.a[0]); for(int i=1;i<=ret.a[0];i++) ret.a[i]=x.a[i]+y.a[i]; for(int i=1;i<=ret.a[0];i++) { int t=ret.a[i]/10; ret.a[i]%=10; ret.a[i+1]+=t; } if(ret.a[ret.a[0]+1])ret.a[0]++; return ret; } N pw(N x) { N ret; ret.a[0]=2*x.a[0]; for(int i=1;i<=x.a[0];i++) for(int j=1;j<=x.a[0];j++) ret.a[i+j-1]+=x.a[i]*x.a[j]; for(int i=1;i<=ret.a[0];i++) { int t=ret.a[i]/10; ret.a[i]%=10; ret.a[i+1]+=t; } if(ret.a[ret.a[0]+1])ret.a[0]++; while(ret.a[ret.a[0]]==0&&ret.a[0])ret.a[0]--; return ret; } void sub(int k) { ans.a[1]-=k; int i=1; while(ans.a[i]<0)ans.a[i]+=10,ans.a[++i]--; while(ans.a[ans.a[0]]==0&&ans.a[0])ans.a[0]--; } void print() { for(int i=ans.a[0];i;i--)printf("%d",ans.a[i]); } int main() { scanf("%d",&n); f[1].a[0]=1; f[1].a[1]=1; f[2].a[0]=1; f[2].a[1]=3; for(int i=3;i<=n;i++) f[i]=add(f[i-1],f[i-2]); ans=pw(f[n]); if(n%2==0)sub(4); print(); return 0; }
还有大家都在说的结论:http://vfleaking.blog.163.com/blog/static/17480763420119685112649/
也就是:f[i] = ( f[i-1]*3 - f[i-2] + 2 )
代码如下:
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int n; struct N{ int a[50005]; // N(){memset(a,0,sizeof a);} }f[105],ans; N sub(N x,N y) { x.a[1]+=2; int j=1; while(x.a[j]>=10){x.a[j]%=10;x.a[j+1]++;j++;} for(int i=1;i<=x.a[0];i++) { x.a[i]-=y.a[i]; if(x.a[i]<0)x.a[i]+=10,x.a[i+1]--; } // for(int i=1;i<=x.a[0];i++) // if(x.a[i]<0)x.a[i]+=10,x.a[i+1]--; while(x.a[x.a[0]]==0&&x.a[0])x.a[0]--; return x; } //N add(N x,int k) //{ // x.a[1]+=k; int i=1; // while(x.a[i]>=10)x.a[i+1]+=x.a[i]/10,x.a[i]%=10,i++; // if(x.a[x.a[0]+1])x.a[0]++; // return x; //} N mul(N x,int k) { for(int i=1;i<=x.a[0];i++)x.a[i]*=k; for(int i=1;i<=x.a[0];i++) { x.a[i+1]+=x.a[i]/10; x.a[i]%=10; } if(x.a[x.a[0]+1])x.a[0]++; return x; } void print() { for(int i=f[n].a[0];i;i--)printf("%d",f[n].a[i]); } int main() { scanf("%d",&n); f[1].a[0]=1; f[1].a[1]=1; f[2].a[0]=1; f[2].a[1]=5; for(int i=3;i<=n;i++) { // f[i]=mul(f[i-1],3); // f[i]=sub(f[i],f[i-2]); // f[i]=add(f[i],2); f[i]=sub(mul(f[i-1],3),f[i-2]); } print(); return 0; }
果然考场上还是打表找规律比较靠谱...
然而为什么,我的代码跑得好慢...