Solved:2
rank:293
J. Sequense
不知道自己写的什么东西 以后整数分块直接用 n / (n / i)表示一个块内相同n / i的最大i
#include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod = 1e9 + 7; ll A, B, C, D, P, n; struct martix { ll c[3][3]; }; martix mul(martix A, martix B) { martix res; memset(res.c, 0, sizeof(res.c)); for(int i = 0; i < 3; i++) for(int j = 0; j < 3; j++) for(int k = 0; k < 3; k++) res.c[i][j] = (res.c[i][j] + A.c[i][k] * B.c[k][j] % mod) % mod, (res.c[i][j] += mod) %= mod; return res; } martix pow_mod(martix x, ll y) { martix res; memset(res.c, 0, sizeof(res.c)); res.c[0][0] = res.c[1][1] = res.c[2][2] = 1LL; while(y) { if(y & 1) res = mul(res, x); x = mul(x, x); y >>= 1; } return res; } int main() { martix og; int T; scanf("%d", &T); while(T--) { scanf("%lld%lld%lld%lld%lld%lld", &A, &B, &C, &D, &P, &n); memset(og.c, 0, sizeof(og.c)); og.c[0][0] = D + 1; og.c[0][1] = C - D; og.c[0][2] = -C; og.c[1][0] = og.c[2][1] = 1; ll f1 = A; ll f2 = B; if(n == 1) { printf("%lld ", A); continue; } if(n == 2) { printf("%lld ", B); continue; } if(n <= 50000) { for(int i = 3; i <= n; i++) { ll tmp = f1 * C % mod + D * f2 % mod + P / i; tmp %= mod; f1 = f2; f2 = tmp; } printf("%lld ", f2); continue; } for(int i = 3; i <= 50000; i++) { ll tmp = f1 * C % mod + D * f2 % mod + P / i; tmp %= mod; f1 = f2; f2 = tmp; } ll now = 50001; ll f3 = C * f1 % mod + D * f2 % mod + P / now; f3 %= mod; //cout<<f3<<endl; ll ans = f3; while(now < n) { if(P / now == P / n) { ans = 0; martix tmp1 = pow_mod(og, n - now); ans = tmp1.c[0][0] * f3 % mod + tmp1.c[0][1] * f2 % mod; ans %= mod; ans += tmp1.c[0][2] * f1 % mod; ans %= mod; ans += mod; ans %= mod; break; } if(now + 10000 >= n) { for(int i = now + 1; i <= n; i++) { ll ttmp = f2 * C % mod + D * f3 % mod + P / i; ttmp %= mod; f1 = f2; f2 = f3; f3 = ttmp; } ans = f3; break; } if(P / (now + 1) != P / now) { for(int i = now + 1; i <= now + 3; i++) { ll tymp = f2 * C % mod + D * f3 % mod + P / i; tymp %= mod; f1 = f2; f2 = f3; f3 = tymp; } now += 3; continue; } ll l = now, r = n; ll mid = l + r >> 1; while(l + 1 < r) { mid = l + r >> 1; if(P / mid == P / now) l = mid; else r = mid; } ll opp; if(P / r == P / now) opp = r; else opp = l; if(opp - now >= 5) { martix tmp2 = pow_mod(og, opp - now - 2); ll tt = 0; tt = tmp2.c[0][0] * f3 % mod + tmp2.c[0][1] * f2 % mod; tt %= mod; tt += tmp2.c[0][2] * f1 % mod; tt %= mod; tt += mod; tt %= mod; tmp2 = mul(tmp2, og); ll ttt = 0; ttt = tmp2.c[0][0] * f3 % mod + tmp2.c[0][1] * f2 % mod; ttt %= mod; ttt += tmp2.c[0][2] * f1 % mod; ttt %= mod; ttt += mod; ttt %= mod; f1 = tt; f2 = ttt; f3 = C * f1 % mod + D * f2 % mod + P / opp; f3 %= mod; now = opp; } else { for(int i = now + 1; i <= opp; i++) { ll tmpp = C * f2 % mod + D * f3 % mod + P / i; tmpp %= mod; f1 = f2; f2 = f3; f3 = tmpp; } now = opp; } } printf("%lld ", ans); } return 0; }