HDU 1005 Number Sequence 寻找周期

原题: http://acm.hdu.edu.cn/showproblem.php?pid=1005

题目:

Number Sequence

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 128931 Accepted Submission(s): 31368

Problem Description
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).

Input
The 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.

Output
For 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

思路:

类似于一个fib数列,但是每项都由前两项分别*a和*b之后再对7取余。
不难想到,f数列的每一项都只能为0到7的值。
那么每两项有7*7=49种情况。
所以第50项的前两项肯定在前面已经出现过了。
所以周期最多可能为49。

就像循环小数一样,后面的循环部分最多有49个字符长度,但是前面的部分不一定属于循环部分,所以我们这里从第100项开始求周期。

代码:

#include <iostream>
#include"stdio.h"
#include"math.h"
#include"string.h"
#include"algorithm"
using namespace std;
typedef long long int lint;
const int N =1000005;
int f[N];

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    int a,b,n;
    f[1]=1;
    f[2]=1;
    while(scanf("%d %d %d",&a,&b,&n)!=EOF)
    {
        int t=-1;
        int st=0;
        if(a==0&&b==0&&n==0)    break;
        //打到250的表,用来找规律,虽然用不到这么多
        for(int i=3; i<=250; i++)
            f[i]=((a%7)*(f[i-1]%7)+(b%7)*(f[i-2]%7))%7;
        //枚举100200内的所有可能的周期起点
        for(int i=100; i<=200; i++)
        {
            for(int j=101; j<=200; j++)
            {
            //找到可能是周期起点的点
                if(f[i]==f[j])
                {
                    t=j-i;
                    //检查这一段是不是周期
                    for(int k=0; k<=t; k++)
                    {
                        if(f[k+i]!=f[k+j])
                            t=-1;
                    }
                }
                st=i;
                if(t!=-1)   break;
            }
            if(t!=-1)   break;
        }
        if(n<=st)   printf("%d\n",f[n]);
        else printf("%d\n",f[(n-st)%t+st]);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值