题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1005
心得:
在OJ平台、博客等很多地方看到有人称此题的循环节为48,并得到了AC,可能是测试数据覆盖范围过小的缘故,我只能说你们得逞了。
下图是某网友的AC算法:
#include<stdio.h>
int main(){
long a,b,n,i,f[100];
while(scanf("%ld%ld%ld",&a,&b,&n) && a!=0){
f[1]=f[2]=1;
for(i=3;i<=48;i++)
f[i]=(a*f[i-1]+b*f[i-2])%7;
printf("%ld\n",f[(n>48)?n%48:n]);
}
return 0;
}
下面我将举例证明其错误:
= 周期不为48的情况 =
= 循环不从1开始的情况 =
= 周期为0的特殊情况 =
(此处周期计算失误,姑且认为周期是0吧)
很容易可以看出周期必然小于49,因为7的余数有7种情况,f(n)有7*7=49种情况。但不能试验几次就简单的认为周期和循环位置固定!
代码:
#include <iostream>
using namespace std;
int main(){
int i,j,k1,k2,n,start,perid,a,b,flag;
int t[55];
while(cin>>a>>b>>n,!(a==0 && b==0 && n==0)){
memset(t,0,sizeof(t));
perid=0;
flag=0;
start=1;
t[1]=1;t[2]=1;
for(i=3;i<55;i++)
t[i]=(a*t[i-1]+b*t[i-2])%7;
for(i=2;i<55;i++){
k1=t[i-1];k2=t[i];
for(j=4;j<55;j++){
if(t[j-1]==k1 && t[j]==k2 && flag==0) {
start=i-1;
perid=j-i;
flag=1;
}
}
}
//调试代码:
/* for(i=1;i<=5;i++){
for(j=10*(i-1)+1;j<=10*i;j++) printf("t[%2d]=%d ",j,t[j]);
}
cout<<"start= "<<start<<" "
<<"perid= "<<perid<<endl;
*/
if(perid) {
n=(n-start+1)%perid+start-1;
if(!n) n+=perid;
cout<<t[n]<<endl;
}
else if(n>=start) cout<<t[start]<<endl;
else cout<<t[n]<<endl;
}
}