题目链接:点我
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 很大,我们不能直接递推出来,那么我们可以用矩阵快速幂来加速这个递推过程,矩阵快速幂的原理其实和快速幂的原理是一样的,只是变成了矩阵乘法.对于递推式
具体矩阵请看代码.
代码:
#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;
}