Funny Function
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 642 Accepted Submission(s): 298
Problem Description
Function Fx,ysatisfies:
For given integers N and M,calculate Fm,1 modulo 1e9+7.
Input
There is one integer T in the first line.
The next T lines,each line includes two integers N and M .
1<=T<=10000,1<=N,M<2^63.
Output
For each given N and M,print the answer in a single line.
Sample Input
2
2 2
3 3
Sample Output
2
33
Source
2017 Multi-University Training Contest - Team 2
题目意思:就是根据一个公式求值,n,m较大。
设a[i] = a[i-1]+2*a[i-2]为x性质。
首先有一个规律就是,F(1,1) F(1,2)F(1,3) ,,,符合x性质。
F(2,1),F(2,2),F(2,3),,,也符合x性质。
证明的话,F(2,1) = F(1,1)+,,F(1,n),F(2,2) = F(1,2)+,,F(1,n+1),F(2,3) = F(1,3),,,+F(1,n+2);因为F(1,1),F(1,2),F(1,3)符合x性质,那么从上面那个式子可以发现,F(2,3)的每一个元素都可以用F(2,1)中的一个元素乘2加上F(2,2)的的一个元素组成,所以F(2,3) = F(2,1)*2+F(2,2);
根据斐波那契的性质,前n项和可以表示为k*a1+m*a2,那么,因为k,m可以用矩阵快速幂求出,求出k,m可以得到f(i,1),f(i,2)到f(i+1,1),f(i+1,2)的转移公式,再用一个矩阵快速幂就可以求出答案了。
#include <stdio.h>
#include <algorithm>
#include <math.h>
#include <vector>
#include <map>
#include <set>
#include <iostream>
#include <string.h>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int mod = 1e9 + 7;
//int mod;
void add(int &a,int b)
{
a += b;
if(a >= mod) a -= mod;
//if(a >= mod) a -= mod;
}
struct matrix
{
int e[4][4],n,m;
matrix() {}
matrix(int _n,int _m): n(_n),m(_m) {memset(e,0,sizeof(e));}
matrix operator * (const matrix &temp)const
{
matrix ret = matrix(n,temp.m);
for(int i=1;i<=ret.n;i++)
{
for(int j=1;j<=ret.m;j++)
{
for(int k=1;k<=m;k++)
{
add(ret.e[i][j],1LL*e[i][k]*temp.e[k][j]%mod);
}
}
}
return ret;
}
matrix operator + (const matrix &temp)const
{
matrix ret = matrix(n,m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
add(ret.e[i][j],(e[i][j]+temp.e[i][j])%mod);
}
}
return ret;
}
void getE()
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
e[i][j] = i==j?1:0;
}
}
}
};
matrix qpow(matrix temp,long long x)
{
int sz = temp.n;
matrix base = matrix(sz,sz);
base.getE();
while(x)
{
if(x & 1) base = base * temp;
x >>= 1;
temp = temp * temp;
}
return base;
}
void print(matrix p)
{
int n = p.n;
int m = p.m;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
printf("%d ",p.e[i][j]);
}
cout << endl;
}
}
int main()
{
int T;
cin >> T;
while(T--){
long long n,m;
scanf("%I64d %I64d",&n,&m);
matrix a = matrix(3,3);
matrix b = matrix(1,3);
matrix ax = matrix(3,3);
ax.e[1][1] = 1,ax.e[2][1] = 1;
ax.e[2][2] = 1,ax.e[3][2] = 2;
ax.e[2][3] = 1;
a = ax;
b.e[1][1] = 1,b.e[1][3] = 1;
a = qpow(a,n-1);
b = b*a;
int k = b.e[1][1];
b.e[1][1] =0,b.e[1][2] = 1, b.e[1][3] = 0;
b = b*a;
int mm = b.e[1][1];
matrix aa = matrix(2,2);
matrix bb = matrix(1,2);
//cout << k << ' '<<mm << endl;
aa.e[1][1] = k,aa.e[2][1] = mm;
aa.e[1][2] = 2*mm%mod;aa.e[2][2] = (k+mm)%mod;
bb.e[1][1] = 1,bb.e[1][2] = 1;
//print(aa);
aa = qpow(aa,m-1);
bb = bb*aa;
printf("%d\n",bb.e[1][1]);
}
}