链接:https://ac.nowcoder.com/acm/contest/885/B?&headNav=acm&headNav=acm&headNav=acm
来源:牛客网
generator 1
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld
You are given four positive integers x0,x1,a,bx_0, x_1, a, bx0,x1,a,b. And you know xi=a⋅xi−1+b⋅xi−2x_i = a \cdot x_{i-1} + b \cdot x_{i-2}xi=a⋅xi−1+b⋅xi−2 for all i≥2i \ge 2i≥2.
Given two positive integers n, and MOD, please calculate xnx_nxn modulo MOD.
Does the problem look simple? Surprise! The value of n may have many many digits!
The input contains two lines. The first line contains four integers x0,x1,a,bx_0, x_1, a, bx0,x1,a,b (1≤x0,x1,a,b≤1091 \le x_0, x_1, a, b \le 10^91≤x0,x1,a,b≤109). The second line contains two integers n, MOD (1≤n<10(106),109输出描述:
Print one integer representing the answer.示例1
输入
复制
1 1 1 1 10 1000000001输出
复制
89说明
The resulting sequence x is Fibonacci sequence. The 11-th item is 89.示例2
输入
复制
1315 521 20185 5452831 9999999999999999999999999999999999999 1000000007输出
复制
914730061题解1:打表可以发现,mod数的结果存在循环节,并且符合积性函数的性质,即:
1、f(a ) = (a - 1)*(a +1)(a为质数)
2、f(a*b) = f(a) * f(b) (a , b 互质)
3、f(a*b) = f(a) * b (a%b==0)
所以,先求出循环节,然后快速幂,注意要用到快速乘
#include
using namespace std; typedef long long ll; const int N = 1e6 + 10; struct node { ll mat[2][2]; }; int prime[N], len; int ok[N]; ll x0, x1, a, b, mod, p; node ans, O, tmp, z; char n[N]; void init() { for(int i = 2; i < N; i++) { if(!ok[i]) prime[len++] = i; for(int j = 0; j < len && (ll)i * prime[j] < N; j++) { ok[i * prime[j]] = 1; if(i % prime[j] == 0) break; } } } ll ksc (ll x, ll y, ll z) { x %= z; y %= z; ll res = 0; while(y) { if(y & 1) res = (res + x) % z; x = (x + x) % z; y >>= 1; } return res; } node cul (node x, node y) { for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) { z.mat[i][j] = 0; for(int k = 0 ; k < 2; k++) { z.mat[i][j] = (z.mat[i][j] + ksc(x.mat[i][k] , y.mat[k][j], mod)) % mod; } } return z; } ll getmod(ll x) { ll ans1 = 1, ans2 = 1, cnt = x; for(int i = 0; i < len && (ll)prime[i] * prime[i] <= x; i++) { if(x % prime[i] == 0){ ans1 *= (prime[i] - 1) * (prime[i] + 1); ans2 *= prime[i]; while(x % prime[i] == 0) x /= prime[i]; } } if(x > 1) { ans1 *= (x - 1) * (x + 1); ans2 *= x; } // cout << cnt << " " << ans1 << " " << ans2 << endl; return cnt / ans2 * ans1; } void solve(ll x) { ans.mat[0][0] = ans.mat[1][1] = 1; ans.mat[0][1] = ans.mat[1][0] = 0; tmp.mat[0][0] = a; tmp.mat[0][1] = b; tmp.mat[1][0] = 1; tmp.mat[1][1] = 0; while(x) { if(x & 1) ans = cul(ans, tmp); tmp = cul(tmp, tmp); x >>= 1; } printf("%lld\n", (ksc(ans.mat[1][0], x1, mod) + ksc(ans.mat[1][1], x0, mod)) % mod); } int main() { init(); ll x = 0; scanf("%lld %lld %lld %lld %s %lld", &x0, &x1, &a, &b, n, &mod); int len = strlen(n); p = getmod(mod); // cout << mod << endl; for(int i = 0; i < len; i++) { x = ksc (x , 10, p) ; x = (x + n[i] -'0') % p; } solve(x); return 0; } 题解2:十倍增的快速幂
#include
using namespace std; typedef long long ll; const int N = 1e6 + 10; struct node { ll mat[2][2]; }; ll x0, x1, a, b, mod; node ans, O, tmp, z; char n[N]; node cul (node x, node y) { for(int i = 0; i < 2; i++) for(int j = 0; j < 2; j++) { z.mat[i][j] = 0; for(int k = 0 ; k < 2; k++) z.mat[i][j] = (z.mat[i][j] + x.mat[i][k] * y.mat[k][j] ) % mod; } return z; } int main() { int op; scanf("%lld %lld %lld %lld %s %lld", &x0, &x1, &a, &b, n, &mod); int len = strlen(n); ans.mat[0][0] = ans.mat[1][1] = 1; tmp.mat[0][0] = a; tmp.mat[0][1] = b; tmp.mat[1][0] = 1; for(int i = len - 1; i >= 0; i--) { op = n[i] - '0'; for(int j = 0; j < op; j++) ans = cul(ans, tmp); O.mat[0][0] = O.mat[1][1] = 1; O.mat[0][1] = O.mat[1][0] = 0; for(int j = 0; j < 10; j++) O = cul(O, tmp); tmp = O; } printf("%lld\n", (x1 * ans.mat[1][0] + x0 * ans.mat[1][1] ) % mod) ; return 0; }