题意
计算 mod $1000000000$。
思路
求循环节
斐波那契数列在模数意义下是有循环节的。
我们把模数分解,然后分别求循环节去合并。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51
|
using namespace std; typedef long long ll; const int N = 8e6 + 10; const int mod[2] = {512, 125 * 125 * 125};
int f[N]; int ans[2]; int n, m;
int (int a, int n, int mod = 1000000000) { int res = 1; while(n) { if(n & 1) res = 1LL * res * a % mod; a = 1LL * a * a % mod; n >>= 1; } return res; }
int main() { scanf("%d%d", &n, &m); for(int k = 0; k < 2; ++k) { f[0] = 0; f[1] = 1; int j = 2; for(; ; ++j) { f[j] = f[j - 1] + f[j - 2]; if(f[j] >= mod[k]) f[j] -= mod[k]; if(f[j] == 0 && f[j - 1] == 1) break; } for(int i = 0; i < j; ++i) { int cnt = n / j + (n % j >= i); ans[k] = (ans[k] + 1LL * cnt * qp(f[i], m)) % mod[k]; } }
ll phi5 = 125*125*25*4, phi2 = 256; assert(mod[1] * 1ll * qp(mod[1], phi2 - 1) % mod[0] == 1); assert(mod[0] * 1ll * qp(mod[0], phi5 - 1) % mod[1] == 1); ll ret = ans[0] * 1ll * mod[1] % 1000000000 * qp(mod[1], phi2 - 1) % 1000000000 + ans[1] * 1ll * mod[0] % 1000000000 * qp(mod[0], phi5 - 1) % 1000000000; assert(ret % mod[0] == ans[0]); assert(ret % mod[1] == ans[1]); ret %= 1000000000; printf("%lldn", ret); return 0; }
|
BM线性递推。
当然也可以用线性递推的利器BM,求出在两个模数下分别的答案然后再中国剩余定理合并。
近期评论