Description
Jzzhu has invented a kind of sequences, they meet the following property:
You are given x and y, please calculate fn modulo 1000000007(109 + 7).
Input
The first line contains two integers x and y(|x|, |y| ≤ 109). The second line contains a single integer n(1 ≤ n ≤ 2·109).
Output
Output a single integer representing fn modulo 1000000007(109 + 7).
Sample Input
2 3 3
1
0 -1 2
1000000006
Hint
In the first sample, f2 = f1 + f3, 3 = 2 + f3, f3 = 1.
In the second sample, f2 = - 1; - 1 modulo (109 + 7) equals (109 + 6).
构造矩阵
f3 = f2 - f1; ====>
f4 = f3 - f2; ====> f4 = - f1;
( -1 1 ) ( f1 ) -----> ( f3 )
( -1 0 ) ( f2 ) -----> ( f4 )
( -1 1 ) ( -1 1 ) ( f1 ) -----> ( f5 )
( -1 0 )( -1 0 ) ( f2 ) -----> ( f6 )
以此类推, 分类讨论
当n是奇数时,乘以矩阵的(n/2 - 1)次方
当n是偶数时,乘以矩阵的(n/2 )次方
当时做题的时候推出了这种思想,细想想还有其他更为简便的方法
#include <iostream>
#include <cstdio>
#include <cstring>
#define Mod 1000000007
int n;
struct Node
{
int m[3][3];
int x;
int y;
}pt , st , dt;
Node Pow(Node a, Node b)
{
memset(dt.m , 0 , sizeof(dt.m));
dt.x = a.x;
dt.y = b.y;
for(int i = 1 ; i <= a.x; i++)
{
for(int k = 1; k <= a.y; k++)
{
if(a.m[i][k] == 0)
continue;
{
for(int j = 1; j <= b.y; j++)
{
dt.m[i][j] = ((dt.m[i][j] + a.m[i][k] * b.m[k][j]) % Mod) % Mod;
}
}
}
}
return dt;
}
void quickpow(int n)
{
while(n)
{
if(n % 2 == 1)
pt = Pow(st , pt);
n = n / 2;
st = Pow(st , st);
}
}
int main()
{
long long int f1,f2,n;
scanf("%lld %lld",&f1,&f2);
scanf("%lld",&n);
memset(pt.m , 0 ,sizeof(pt.m));
memset(st.m , 0 , sizeof(st.m));
pt.m[1][1] = pt.m[2][2] = 1; //初始化单位矩阵
st.m[1][2] = 1;
st.m[1][1] = st.m[2][1] = -1;//已知矩阵
pt.x = pt.y = 2;
st.x = st.y = 2; //矩阵的行列长度
long long int t;
long long int sum;
if( n % 2 == 1)
{
t = n / 2;
quickpow(t);
sum = pt.m[1][1] * f1 + pt.m[1][2] * f2;
sum = sum%Mod;
if(sum < 0)
sum += Mod;
printf("%lld\n",sum);
}
else
{
t = n /2 - 1;
quickpow(t);
sum = pt.m[2][1] * f1 + pt.m[2][2] * f2;
sum = sum%Mod;
if(sum < 0)
sum += Mod;
printf("%lld\n",sum);
}
return 0;
}