HDOJ 1005:取余,循环,找规律

6 篇文章 0 订阅

第一印象就是斐波那契啊,迭代一下吧,不过TLE了

然后就开始查思路,归纳如下:这个数列必然是重复某个部分的,理由如下,我觉得理由2好像好懂一点,不过数学太差,不知道有没有数学根基

1、因为公式是f(n) = (A * f(n – 1) + B * f(n – 2)) mod 7,所以f(n)=(A%7*f(n-1)+B%7*f(n-2))%7,A%7与B%7的值的范围只有0~6,也就是说循环体最大是49。那就可以用一个大于49的数组来保存f(n),直到找出循环为止。

2、因为循环的条件就是有2个数m和n
f[m-1] = f[n-1], f[m] = f[n]
这样就会开始循环了。
即f[n-1], f[n]与之前的[m-1],f[m]分别对应
而 0 <= f[n-1],f[n] < 7
所以f[n-1]f[n]连着的情况有7*7的情况。
只需每次求出一个f[n],然后比较f[n-1]f[n]与前面数的情况即可。

所以在一定范围内f[50]就会出现重复——循环节


那么这么找这个循环的周期,和循环的开始呢?

网上有些人是认为f[1],f[2]是循环的开始,然后找连续两个1就当作循环的结尾,但是f[50]内可能是这样的:

1 1 2 3 0 4 2 3 0 4...

所以还是按照思路来实现,找重复出现的两个数:

找到了循环的周期(循环末位减循环的开始),循环的开始之后,就将n映射到f[50]内的结果里,看代码:


#include <iostream>
using namespace std;

int main()
{
    int a,b,n,t,beg;
    while(cin>>a>>b>>n && a)
    {
        int f[51] ={-1} ;
        f[1]=f[2]=1;
        bool ck =false;
        for(int i=3;i<=51;i++)
        {
            f[i] = (f[i-1]*a+f[i-2]*b)%7;
            for(int j=2;j<i;j++)
            {
                if(f[j]==f[i] && f[j-1]==f[i-1])
                {
                    t = i-j;
                    beg = j-1;
                    ck = true;
                    break;
                }
            }
            if(ck)
                break;
        }
        if(n<beg)
            cout<<f[n]<<endl;
        else
            cout<<f[beg+(n-beg)%t]<<endl;
    }
}

参考了betabone的代码,但是呢,我要加多一个ck检查才可以AC,难道是RP的问题?


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值