数论专题hdu1005
本题题意:给出公式a[i] = (A*a[i-1] + B*a[i-2]),输入A,B,n,求其第n项。
代码如下:
/* #include <iostream> using namespace std; int main() { int A,B,n; A = B = 1; int k,z; for(int i=1;i<=1000;i++){ for(int j=1;j<=1000;j++){ A = i; B = j; int a[300] = {0,1,1}; for(k=3;k<=200;k++){ a[k] = (A*a[k-1] + B*a[k-2])%7; for(z=2;z<k;z++){ if(a[k] == a[z] && a[k-1] == a[z-1]){ cout << "A = " << A << " B = " << B << " " << a[k-1] << " " << a[k] << " z=" << z << " k=" << k << endl; break; } } if(z!=k)break; } } } return 0; } 打了个表发现B为7的倍数时,且A > 1 && A < 7 表达式为: a[i] = A*a[i-1]%7 例子: A = 2 1 1 2 4 1 2 A = 3 1 1 3 2 6 4 5 1 3 当A为7的倍数时,正常循环 而A和B同时为7的倍数时,除a[1],a[2],全为0 综合上述,情况我们就可以写出一个比较可靠的程序了 */ #include <iostream> using namespace std; int i,j; int main() { int A,B,n; while(cin >> A >> B >> n && (A || B || n)){ // 首先n=2的情况,肯定是1,这是毫无疑问的 if(n == 1 || n == 2){ cout << 1 << endl; continue; } // 然后从打表的结果来看,就是注释里的那个程序,当A和B为7的倍数,无论n是什么,结果必为0(此处已排除n取1,2的情况)。 if(A % 7 == 0 && B % 7 == 0){ cout << 0 << endl; continue; } // 然后进入正题了(前两个if只是为了剪枝,去掉也不会影响代码的正确性),由于mod7,所以前后两个数的排列小于等于49,为了表达49个排列就要打印出前50项 // 举例:mod2的时候,就是 0 0 1 1 0,这样就包含了所有的4个排列 int a[51] = {0,1,1}; int l; for(i=3;i<=50;i++){ a[i] = (A*a[i-1] + B*a[i-2]) % 7; for(j=2;j<i;j++){ if(a[i] == a[j] && a[i-1] == a[j-1]){ break; } } if(j!=i)break; }// 假设打印出的数组是1 1(j) 2 3 4 1 1(i),那么此时的i,j的位置就如前所示 i -= 2; j -= 2; // 然后进行减二操作是为了将循环的部分,复制到loop数组中,保险起见,这里我们把数组开到了51 int loop[51]; for(int k=j+1;k<=i;k++) { loop[k-j-1] = a[k]; } // 然后当n在第一节,也就是包含了不循环部分和第一个循环部分的范围内时,直接按下标输出,通过打表发现不循环的部分只有在B%7==0的时候会有一个1的前缀,其他都是以1 1 开头的循环 if(n <= i){ cout << a[n] << endl; } // 若n位与其后的部分,就对循环节的长度进行取模,这里i-j就是循环节的长度,由于loop数组是以0为下标开头的,因此n在减去j的基础上还要减1 else{ cout << loop[(n-j-1)%(i-j)] << endl; } } return 0; }
这道题真的挺坑的,主要是之前实在想不出来就去查题解,然后题解一眼望上去居然是错的,然后就纠结了两天,终于灵光一闪,打表给ac了。