题目链接:点我
题目
Jzzhu has invented a kind of sequences, they meet the following property:

You are given x and y, please calculate fn modulo 1000000007 (1e9 + 7).
Input
The first line contains two integers x and y (|x|, |y| ≤ 1e9). The second line contains a single integer n (1 ≤ n ≤ 2·1e9).
Output
Output a single integer representing fn modulo 1000000007 (1e9 + 7).
Example
Input
2 3
3
Output
1
Input
0 -1
2
Output
1000000006
Note
In the first sample, f2 = f1 + f3, 3 = 2 + f3, f3 = 1.
In the second sample, f2 = - 1; - 1 modulo (1e9 + 7) equals (1e9 + 6).
题意:
计算递推式的第n项对1e9 + 7 取模.
思路:
矩阵快速幂, 由于题目所给的 n 很大,我们不能直接递推出来,那么我们可以用矩阵快速幂来加速这个递推过程,矩阵快速幂的原理其实和快速幂的原理是一样的,只是变成了矩阵乘法.对于递推式
具体矩阵请看代码.
代码:
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 52 53 54 55 56 57
| #include<cstdio> #include<algorithm> #include<cstring> #include<iostream> #include<cmath> using namespace std;
typedef long long LL; const int mod = 1e9 + 7;
struct mat{ LL a[3][3]; mat(){memset(a, 0 ,sizeof(a));} mat operator *( mat b){ mat c; for(int i = 1; i <= 2; ++i) for(int k = 1; k <= 2; ++k){ if(a[i][k]) for(int j = 1; j <= 2; ++j){ c.a[i][j] += a[i][k] * b.a[k][j] ; c.a[i][j] = (c.a[i][j] % mod + mod ) %mod; } }return c; } };
mat qpow(mat x, LL n){ mat ans; ans.a[1][1] = ans.a[2][2] = 1; while(n){ if(n & 1) ans = ans * x; x = x * x; n >>= 1; } return ans; }
int main(){ LL x, y, n; scanf("%I64d %I64d %I64d", &x, &y, &n); x = (x % mod + mod) % mod; y = (y % mod + mod) % mod; if(n == 1){ printf("%I64d\n",(x + mod ) % mod); return 0; } if(n == 2){ printf("%I64d\n",(y + mod) % mod); return 0; } mat q; q.a[1][1]= q.a[2][1] = 1; q.a[1][2] = -1; mat ans ; ans = qpow(q, n-2); LL sum = ans.a[1][1] * y % mod + ans.a[1][2] * x % mod; printf("%I64d\n", (sum% mod + mod) % mod); return 0; }
|