Number Sequence HDU-1005

Number Sequence

  HDU - 1005 

A number sequence is defined as follows: 

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). 
InputThe input consists of multiple test cases. Each test case contains 3 integers A, B and n on a single line (1 <= A, B <= 1000, 1 <= n <= 100,000,000). Three zeros signal the end of input and this test case is not to be processed. 
OutputFor each test case, print the value of f(n) on a single line. 
Sample Input
1 1 3
1 2 10
0 0 0
Sample Output
2
5

题意非常简单,

但是过大的n使得我们不能从头到尾跑一遍。

第一想法就是找规律,一定是循环的,

但是a,b未知,很难建立周期长度和a,b的关系。

最开始打算朴素地从第一个开始找,直到找到有连续两位相同的就结束(因为第三项是由前两项决定的,前两项相同第三项一定相同),算出周期长度,然后算出来,但是一度没想明白,怕万一超时了,然而,当我看到网上一篇与这道题有关的题解时,

我发现我果然

想多了……

模7后,每个数只有7种可能,连续两个数的组合只有49种可能,因此连续51个数,共有50个连续二元有序数对,这样根据抽屉原理,必有两个有序数对相同,因此必定发生了循环,因此只要枚举到第51位就行了,此时记录下发生循环的起始位置和循环长度,最后对n取个模处理一下就可以了。

但是看到的题解里默认循环起始位置是第一个数,然后我和它的AC程序比较了一下,随机生成a,b,n=4,3,117时,对方那篇题解就在第49个数发生了问题,至于能AC,我想恐怕是RP爆发吧,可能是数据太弱了的缘故。

最后,附上我的代码

#include<cstdio>
#include<cstdlib>
#include<time.h>
int main()
{
srand(time(NULL));//大家可以自动忽略这一行,本来是为了随机函数进行比较的
int a,b,n,i,j,k,d;bool bo=false;
int f[100]={0};
int p[100]={0};
scanf("%d%d%d",&a,&b,&n);
while (a!=0&&b!=0&&n!=0) {
a=a%7;b=b%7;bo=false;
f[1]=1;f[2]=1;k=1;
for (i=3;i<60;i++) 
{
f[i]=(a*f[i-1]+b*f[i-2])%7;
for (j=1;j<i-1;j++)
if (f[j]==f[i-1]&&f[j+1]==f[i]) {
bo=true;
k=j;
break;
}
if (bo) {
d=i-k-1;break;
}
}
printf("%d\n",f[(n-k)%d+k]);
scanf("%d%d%d",&a,&b,&n);

}

return 0;

}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值