HDOJ1005

Number Sequence

这一题拿到手,第一感觉是不会太难,毕竟算是比较靠前的题目,呵呵。随手写了一个,也知道应该会挂掉,因为1 <= n <= 100,000,000,

#include <iostream>
using namespace std;
int main()
{
    int a,b,n;
    while(cin>>a>>b>>n && n)
    {
        int f1 = 1,f2 = 1,f,count = 3;
        while(count <= n)
        {
            f = (a*f2 + b*f1)%7;
            f1 = f2;
            f2 = f;
            count++;
        }
        cout<<f<<endl;
    }
    return 0;
}

不出意料地挂了,需要另寻他路。

暂时没有其他想法,第一反应是0<=f(n)<=6,而且一旦A、B的值给定,序列f(1)、f(2)、f(3)、…f(n)会出现循环。按照这个思路去试了一下题目给出的两个测试例子,果不其然,当(A,B)=(1,1)的时候,出现了循环,循环长度为16;当(A,B)=(1,2)时,也出现了循环,循环长度为12。

再进一步分析,观察给出的公式,

f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7,
f(3)=(A+B)%7,
f(4)=(A*((A+B)%7)+B)%7,…,
f(n)=(A%7*f(n-1)+B%7*f(n-2))%7,

0<=A%7,B%7<=6,所以循环的长度不会超过7*7=49.

循环的过程是这样的:

f = (a*f2 + b*f1)%7;
f1 = f2;
f2 = f;

也就是说到了某个阶段,会出现f(m-1) = f(n-1), f(m) = f(n),m<n不一定是从1,1开始循环的。所以思路很明显了,定义一个长度大于49的数组,对于确定的A、B,记录前面50次算出的结果,找出循环的部分即可。关键就是找到循环周期和循环的开始,一个比较笨的方法就是对于每次算出一个f(n),就比较f(n)和f(n-1)与之前算出的结果,如果能够找到一个m,m<n,满足f(m-1) = f(n-1), f(m) = f(n),循环的周期自然就是n-m,对应的f(n)做一个映射就可以找到其值。

#include <iostream>
using namespace std;
int main()
{
    int a,b,n,len,start;
    while(cin>>a>>b>>n&&n)
    {
        int f[51]={-1};
        f[1]=1,f[2]=1;
        for(int i=3;i<51;i++)
        {
            f[i]=(a*f[i-1]+b*f[i-2])%7;
            for(int j=2;j<i;j++)
            {
                if((f[j]==f[i])&&(f[j-1]==f[i-1]))
                {
                    len=i-j;
                    start=j-1;
                    break;
                }
            }
        }
        if(n<start)
        {
            cout<<f[n]<<endl;
        }
        else
        {
            cout<<f[start+(n-start)%len]<<endl;
        }
    }
    return 0;
}

当然还有其他解法,异曲同工。这篇博客写得比较详细

http://www.cnblogs.com/krisdy/archive/2009/04/12/1434013.html

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-04 07:15:17

HDOJ1005的相关文章

HDOJ1005 数列

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 cont

ACM—Number Sequence(HDOJ1005)

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=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). 看到这样的公式很容易想到递归调用求解,但是在本题中n的取

hdoj-1005 找规律

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 cont

HDOJ-1005 Number Sequence

http://acm.hdu.edu.cn/showproblem.php?pid=1005 给出两个初值f(1) = 1:f(2) = 1 和 递推公式f(n) = (a * f(n - 1) + b * f(n - 2)) % 7 输入a,b,n 要求输出f(n) 1 <= n <= 100,000,000这个限制条件表示直接迭代n次注定是超时的结局 由迭代公式知道f(n)都由前两个数推导出来 而每个数都有7种可能 所以共有7*7=49种组合 所以根据鸽巢原理知 由该递推公式推导出50个连

hdoj1005 疯了

……提交30次…… 手残把之前写的页面关了……万分悲痛的心路历程就略了吧…… 题目大意: 1.多组测试数据,依次输入A,B,n(1 <= A, B <= 1000, 1 <= n <= 100,000,000),输入0 0 0 终止: 2.f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7: 3.输出 f(n). 解题思路: 1.n的数值很大,这类数值很大的问题一般都有规律,找出循环节(周期)是关键: 2.找

[HDOJ1005]Number Sequence

Number Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 124651    Accepted Submission(s): 30286 Problem Description A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A

Number Sequence (HDoj1005)

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 co