HDU 1005 Number Sequence【多解,暴力打表,鸽巢原理】
Number Sequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 175657 Accepted Submission(s): 43409
f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7.
Given A, B, and n, you are to calculate the value of f(n).
1 #include <bits/stdc++.h> 2 using namespace std; 3 int f[55]; 4 int main() 5 { 6 int a,b,n; 7 f[1]=1; 8 f[2]=1; 9 while(scanf("%d%d%d",&a,&b,&n)&&a&&b&&n) 10 { 11 int T=0; 12 for(int i=3;i<=51;i++) 13 f[i]=(a*f[i-1]+b*f[i-2])%7; 14 cout<<f[n%51]<<endl; 15 } 16 }
但是,但是,,,,,,这种解法是存在问题的,我以51为周期也会过,只能说后台数据太水了,随便拿一组数据去测48为周期,比如7,7,50/51,输出结果应该为0,但是输出会等于1,明显解法是错误的,于是就有以下两种解法:
方法一:很容易想到有规律 打表也能看出有规律 但是对于每组 A,B规律却不一样 循环节不同
我一开始是找的从第一个数据开始的循环节 但是循环节不一定从第一个位置开始 所以我的毫无疑问会错!
下面给出第一种解法的AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 int f[100000005]; 4 int main() 5 { 6 int a,b,n,t; 7 f[1]=1; 8 f[2]=1; 9 while(scanf("%d%d%d",&a,&b,&n)&&a&&b&&n) 10 { 11 int T=0; 12 for(int i=3;i<=n;i++) 13 { 14 f[i]=(a*f[i-1]+b*f[i-2])%7; 15 for(int j=2;j<i;j++) 16 { 17 if(f[i-1]==f[j-1]&&f[i]==f[j]) 18 { 19 T=i-j; 20 t=j; 21 break; 22 } 23 } 24 if(T>0) 25 break; 26 } 27 if(T>0) 28 { 29 f[n]=f[(n-t)%T+t]; 30 } 31 cout<<f[n]<<endl; 32 } 33 return 0; 34 }
方法二:鸽巢原理,请参看鸽巢原理
因为f[i]只能取0~7,下面的程序用mp[x][y],记录f[i]的值x y相邻时候出现过,鸽巢原理知,状态总数不会超过7*7!
下面给出AC代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 int f[105],mp[8][8]; 4 int main() 5 { 6 int n,a,b,k,x,y; 7 while(scanf("%d%d%d",&a,&b,&n)&&a&&b&&n) 8 { 9 memset(mp,0,sizeof(mp)); 10 f[1]=1; 11 f[2]=1; 12 x=1; 13 y=1; 14 k=3; 15 while(!mp[x][y]) 16 { 17 mp[x][y]=k; 18 f[k]=(a*y+b*x)%7; 19 y=(a*y+b*x)%7; 20 x=f[k-1]; 21 k++; 22 } 23 int h=mp[x][y]; 24 if(n<k) 25 { 26 printf("%d\n",f[n]); 27 } 28 else printf("%d\n",f[(n-h)%(k-h)+h]); 29 } 30 return 0; 31 }
作 者:Angel_Kitty
出 处:https://www.cnblogs.com/ECJTUACM-873284962/
关于作者:阿里云ACE,目前主要研究方向是Web安全漏洞以及反序列化。如有问题或建议,请多多赐教!
版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信我
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角【推荐】一下。您的鼓励是作者坚持原创和持续写作的最大动力!
欢迎大家关注我的微信公众号IT老实人(IThonest),如果您觉得文章对您有很大的帮助,您可以考虑赏博主一杯咖啡以资鼓励,您的肯定将是我最大的动力。thx.
我的公众号是IT老实人(IThonest),一个有故事的公众号,欢迎大家来这里讨论,共同进步,不断学习才能不断进步。扫下面的二维码或者收藏下面的二维码关注吧(长按下面的二维码图片、并选择识别图中的二维码),个人QQ和微信的二维码也已给出,扫描下面👇的二维码一起来讨论吧!!!
欢迎大家关注我的Github,一些文章的备份和平常做的一些项目会存放在这里。