杭电problem1005-Number Sequence

来源:互联网 发布:为什么服务器用centos 编辑:程序博客网 时间:2024/05/17 04:16
本题思路:给出的公式,第一个想到的是递归,使用递归实现,果然超内存,因为1 <= n <= 100,000,000(嘿嘿,我知道不用试也应该知道);接下来尝试使用栈的方式实现,超时了,至此偷懒不成功,开始寻找更好的方法吧。

     最终通过网上各种查找,再加上自己的思考和摸索,理解如下:

   (1)很明显f(n)的取值范围为0~6 

   (2)在A,B给定的情况下,f(n)的值由f(n-1)的值和f(n-2)的值决定

   (3)考虑数列的可能值,f(1)=1,f(2)=1,f(3)=*,f(4)=*,f(5)=* ....................f(49)=*,f(50)=*,f(51)=*,f(52)=*   ............ 。其中‘*’表示值为0~6之间的任意数。将f(1)f(2)这样某两个数放在一起,称为“数值对”(我自己取得名字,方便称呼而已),那么这个数列就可以构成下列的数值对f(1)f(2)、f(2)f(3)、f(3)f(4)、f(4)f(5)......f(49)f(50)、f(50)f(51)、f(51)f(52)等等。现在看这些数值对m1m2,由于m1、m2的取值范围为0~6,那么m1m2数值对的可能情况一共有49种,即00、01、02、04、05、06、10、11、12、13、14、15、16、20.....64、65、66共49(7*7)种。再看数值对f(1)f(2)、f(2)f(3)、f(3)f(4)、f(4)f(5)......f(49)f(50)、f(50)f(51)、f(51)f(52).....,到f(49)f(50)这里时,刚好是第49个数值对,所以说f(50)f(51)一定会和f(1)f(2)~f(49)f(50)中的某个数值对是相同的(因为数值对的所有可能一共是49个嘛,所以最晚到这个时候已经开始出现重复了,当然也可能从f(50)f(51)之前的某个数值对就已经重复了)。

  (4)至此我们可以确定,f(50)f(51)一定会和f(1)f(2)~f(49)f(50)中的某个数值对是相同的,也就是说f(50)会等于f(n),n为0~49之间的某个数,而f(51)等于f(n+1)。因为在A、B确定的情况下,f(n)的值由f(n-1)和f(n-2)确定,那么f(n+2)的值也由f(n+1)和f(n)决定,那么我们就找到了一个循环节,也就是f(n)f(n+1)f(n+2)....和f(50)f(51)f(52)...是相同的序列。而50-n的值即为循环周期。

  (5)找到循环周期和循环节之后,问题就可以简化了,假设m是个很大的数,f(m)一定会和f(1)~f(49)中的某个数相等。

  (6)看了网上的各种题解之后,我的一些个人理解:我不认为循环周期一定是49,也不认为开始产生循环的那个数值对一定是“11”。列如,在a=10,b=21时,就会发现数列的循环周期是48,最开始的11数值对就只出现了一次,整个数列是从f(2)f(3)开始出现循环的。该情况的测试代码也会在最后给出。


wa的代码

#include<iostream>#include<stdio.h>using namespace std;/* * f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7. */ long function(long n, int A, int B) {if (n == 1) {return 1;} else if (n == 2) {return 1;} else {return (A * function(n - 1, A, B) + B * function(n - 2, A, B)) % 7;}}int  main() {int A = 0, B = 0;long n = 0;while(cin>>A>>B>>n) {if(n==0&&A==0&&B==0){return 0;}long ans = function(n, A, B);cout<<ans<<endl;}return 0;}

AC代码版本:

#include<stdio.h>int main(){    int    A,B,i;    long int n;    while(scanf("%d%d%ld",&A,&B,&n)!=EOF)    {        int a[50];        a[1]=1;        a[2]=1;        if((A+B+n)==0)break;        for(i=3;i<=48;i++)        {            a[i]=(A*a[i-1]+B*a[i-2])%7;        }        n=n%48;        a[0]=a[48];        printf("%d\n",a[n]);    }    return 0;}










原创粉丝点击