杭电1005题

      由于本人刚涉ACM,水平有点菜,再加上一直在准备考研,所以很难抽时间也很有限的去AC,1005题个人感觉有点难,因此最后 还是看了别人的解答,贴在下面了。

  

#include <iostream>
using namespace std;
int seq[50];
int main()            
{
    int A,B,n,i;
    while(scanf("%d%d%d",&A,&B,&n) && A+B+n)    
    {
        seq[1]=seq[2]=1;
        for(i=3;i<50;i++)    
        {
            seq[i]=(A*seq[i-1]+B*seq[i-2])%7;
            if(seq[i]==1 && seq[i-1]==1)
                break;
        }
        n%=(i-2);
        if(n==0)
            cout<<seq[i-2]<<endl;
        else
            cout<<seq[n]<<endl;
    }
    return 0;
}

这是AC代码,方法是找循环节

因为mod7的关系,而且f(1)=f(2)=1,所以f(n)的值是循环分布的,而且一定会回到f(n-1)=f(n)=1,并且还可得出,这个循环不大于49,因为相邻连个f只有7种取值,这样f(n-1)和f(n)共有49种组合。所以,只要找出循环因子即可,寻找方法正是根据f(n-1)=f(n)再次出现的地方来计算

这是网上的说法,但明显有问题。如:把50改成99,WA
如果一定存在不大于49的寻环节,并且回到f(n-1)=f(n)=1,则不会存在上述问题

找循环节的思路存在以下问题:
1.如何证明一定存在循环节
2.如果存在循环节,循环的范围有大
3.循环一定回到f(n-1)=f(n)=1吗?
  可能在中间莫些值循环而不回到f(n-1)=f(n)=1

哪位大牛能回答以上问题还请多多指教
----------------------------------------------------------------------------------
先使用一个自定义的词,循环对,即两个相邻的数,以后循环起点都是这一对数

。
我大概的只说说,别让我证明。
1,由于f(n)与f(n-1)和f(n-2)有关,只要出现循环对,就一定会出现循环节。
2,由于是mod 7,共有49种不重复的相邻数对,即50个数,也就是说在这50个数

里,可能不会出现循环对。而在第51个数出现的时候,即有50个相邻数对的时候

,肯定能找到循环对。
3,循环对不一定是f(n-1)=f(n-2)=1.比如当A=513,B=98的时候,循环对是1和2,

循环节是1,2,4.f(1)=1是没有进入循环的。

所以楼主贴出的那个代码是错误的。我猜测它的错误点在于
1,它假设了在49个数里一定出现循环对,for循环里使用了i<50。而49个数

里才有48个相邻数对,可以不出现循环对。
2,它还假定了循环对一定是1,1,循环体里的跳出条件。而很明显,对于当

A=513,B=98的时候,循环对就不是1,1了。这个AC了的程序,当在49个数里找不

到循环对1,1的时候,这时i=50,假设了循环节长度为48个数。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值