PE 440 【二阶递推】
来源:互联网 发布:sql tools 编辑:程序博客网 时间:2024/06/01 22:57
被拖进的坑,555
题目大意:有10种长度为1的木块,1种长度为2的木块,设
容易得到递推式
和Fibonacci数列相似,我们可以推出它一些相关的性质
T(n)的通项公式:
可得
1)
证明 :
2)
证明:
所以可得
设
证明:
i) 最终 a = b = g,值为
若
ii) 出现 a 或 b == 0,值为 c mod 2 + 1
现在就可以考虑枚举 a,b,这样需要先预处理出
但是
循环节长度为987898788
//PS:这里并没有形成
所以求
复杂度
【答案】970746056
#include<iostream>#include<algorithm>#include<cstdlib>#include<cstdio>#include<string>#include<cstring>#include<ctime>#include<cmath>#define N 2000#define M 987898789#define LL long longusing namespace std;LL ans;LL sum[N+5];LL A[2][2],B[2][2],t[2][2];LL ksm(LL a,LL b,LL c){ LL ret = 1; for (;b;b >>= 1,a = a * a % c) if (b & 1) ret = ret * a % c; return ret;}LL mul(LL a[][2],LL b[][2]){ for (int i = 0;i < 2;i ++) for (int j = 0;j < 2;j ++) { t[i][j] = 0; for (int k = 0;k < 2;k ++) (t[i][j] += a[i][k] * b[k][j]) %= M; } for (int i = 0;i < 2;i ++) for (int j = 0;j < 2;j ++) a[i][j] = t[i][j];}LL matrix_ksm(LL b){ A[0][0] = 10,A[0][1] = A[1][0] = 1,A[1][1] = 0; B[0][0] = B[1][1] = 1,B[0][1] = B[1][0] = 0; for (;b;b >>= 1,mul(A,A)) if (b & 1) mul(B,A); return B[0][0];}int gcd(int a,int b){ return b ? gcd(b,a % b) : a;}int main(){ for (int i = 1;i <= N;i ++) for (int j = 1;j <= N;j ++) (sum[i] += matrix_ksm(ksm(j,i,M - 1))) %= M; for (int a = 1;a <= N;a ++) for (int b = 1;b <= N;b ++) { int g = gcd(a,b); if (((a / g) & 1) && ((b / g) & 1)) (ans += sum[g]) %= M; else (ans += 11000) %= M; } cout << ans << endl; return 0;}