杭电1005 Number Sequence

本文探讨了一个特定数列的周期性特点,通过两种不同的方法计算数列中的第n项值,对比了两种方法的差异,并深入分析了周期性的原因。

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
首先对于这道题,网上也有很多答案,并且都通过了hdu的测试,我试过他们的代码,都能通过。虽然都能通过,但是代码却不一定正确。接下来看一下网上通过hdu测试的代码(按照他们的思想,我自己写的代码):

#include <iostream>
#include<string>
using namespace std;
int main()
{
    int a[50];
    int A,B,n;
    cin>>A>>B>>n;
    a[1]=1;
    a[2]=1;
    for(;A!=0||B!=0||n!=0;)
    {
        for(int i=3;i<=49;i++)
        {
            a[i]=(A*a[i-1]+B*a[i-2])%7;
        } 
        a[0]=a[49];  //防止周期恰好是49,这样取模之后值为0
        cout<<a[n%49]<<endl;
        cin>>A>>B>>n;   //进行下一轮取值
    } 

    return 0;
}

我们来写一下测试数据代码(目的是输出f(1)到f(200)之间的值,便于寻找周期和比较结果值):

#include <iostream>
#include<string>
using namespace std;
int main()
{
    int a[205];
    int A,B,n;
    cin>>A>>B>>n;
    a[1]=1;
    a[2]=1;
    cout<<1<<" "<<1<<endl;
    cout<<1<<" "<<2<<endl;

    for(int i=3;i<=200;i++)
    {
        a[i]=(A*a[i-1]+B*a[i-2])%7;
        cout<<a[i]<<" "<<i<<endl;
    }
    return 0;
}

以A=1,B=1,为例,结果如下(第一列代表f(n),第二列值代表n):
测试1
仅选取了部分结果。我们看到当n=52时,f(52)=3;
那么用上述通过hdu测试的代码算出的结果是:
测试2
为什么结果不一致?因为按照上述算法,n=52,要对49取模,结果是3,f(52)=f(3)=2;
这时候就会出现,对于n>49,f(n)的值变成了f(n-1),结果都向后推移了一位。

原本结果
f(49)=1f(49)=1
f(50)=1f(50)=1
f(51)=2f(51)=1
f(52)=3f(52)=2
f(53)=5f(53)=3

这是对49取模的结果,虽然我不太明白,为什么要mod49,但49并不是其周期,故出现了连续三个1的结果,这样的结果居然还通过了测试!如果有理解的望大神指点。
接下来贴出我认为正确的代码(同样通过了hdu测试):

/*
    具体思想:先求其周期,然后用周期对n求模
    因为之前在求周期时已经将前200个结果存于数组,故求模后可直接去数组中取值
    有人可能不理解为么要用前100个数据求周期,如果周期比100大怎么办?
    这个可能就要用到上面的49这个数字了:f(n)最多有7中可能,那么,f(n-1)+f(n-2)最多有7*7=49中可能,故周期一定会在49以内。
    将数组放缩到50应该也是可以的。
    */
#include <iostream>
#include<string>
using namespace std;
int main()
{
    int a[100];
    int A,B,n,i;
    cin>>A>>B>>n;
    a[1]=1;
    a[2]=1;
    for(;A!=0||B!=0||n!=0;)
    {
        //测试一组数据,寻找周期
        for(i=3;i<100;i++)
        {
            a[i]=(A*a[i-1]+B*a[i-2])%7;
            if(a[i]==1&&a[i-1]==1)  break;
        } 
        i=i-2;  //此时i是其真正周期
        n=n%i;  //n对周期取模
        if(n==0) n=i;   //对n取模会出现0的情况,a[0]不存在,故n赋值周期
        cout<<a[n]<<endl;
        cin>>A>>B>>n;  //输入下一组数据
    } 

    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值