Problem I: Water Problem
Time Limit:3000/1000 MS (Java/Others) Memory Limit:163840/131072 KB (Java/Others)
Total Submissions:1405 Accepted:154
Description
函数 f:Z+→Zf:Z+→Z。已知 f(1),f(2)f(1),f(2) 的值,且对于任意 x>1x>1,有 f(x+1)=f(x)+f(x−1)+sin(πx2)f(x+1)=f(x)+f(x−1)+sin(πx/2)。
求 f(n)f(n) 的值。
Input
多组数据。(数据组数 T≤100T≤100)
每组数据包含 33 个不超过 109109 的正整数,分别代表 f(1),f(2)f(1),f(2) 和 nn 的值。
Output
输出 f(n)mod(109+7)f(n)mod(109+7)。每组输出末尾有换行符。
Sample Input
1 2 3
1 2 5
Sample Output
3
7
快速幂可以在o(logn)时间内求a^n%mod,求a^n%mod可以变为求a^(n/2)*a^(n%2)%mod
矩阵快速幂也是用了类似的方法,把矩阵的n次幂变成n/2使其可在o(logn)的复杂度内求解。
f(x)和f(x+1)关系已知,又因为n有1e9的所以只能矩阵快速幂求解 设[f(2),f(1),1]为初始矩阵乘n次下面的矩阵后
[ 1,1,0] [ 1,1,0] [ 1,1,0] [ 1,1,0]
[ 1,0,0] [ 1,0,0] [ 1,0,0] [ 1,0,0]
[ 0,0,1] [-1,0,1] [ 0,0,1] [ 1,0,1]
后变成[f(2+4*n),f(1+4*n),1]所以直接手算上面矩阵结果(手算比较快)
[ 5, 3,0]
[ 3, 2,0]
[-1,-1,1]
然后用矩阵快速幂求解,如所求f(x)中x不是2+4*n则求使2+4*n小于x的最大n。再用f(x+1)=f(x)+f(x-1)+sin(pi*x/2)求解即可
下面是代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define mod 1000000007
struct matrix
{
ll m[3][3];
matrix(){
memset(this->m,0,sizeof(this->m));
}
};
matrix r4;
matrix mul(matrix A,matrix B)
{
matrix ret;
for(int i=0;i<3;i++)
for(int j=0;j<3;j++)
{
ret.m[i][j]=0;
for(int k=0;k<3;k++)
ret.m[i][j]+=A.m[i][k]*B.m[k][j]%mod;
}
return ret;
}
matrix pow(matrix A,long long n)
{
matrix ret;
ret.m[0][0]=1;ret.m[1][1]=1;ret.m[2][2]=1;
while(n)
{
if(n&1)
ret=mul(ret,A);
A=mul(A,A);
n>>=1;
}
return ret;
}
int main()
{
long long si[5]={0,1,0,-1};
int n;ll a,b,c,aans;long long ans2,ans1,tmp;
r4.m[0][0]=5; r4.m[0][1]=3; r4.m[1][0]=3; r4.m[1][1]=2; r4.m[2][1]=-1; r4.m[2][0]=-1; r4.m[2][2]=1;
while(scanf("%lld%lld%lld",&a,&b,&c)!=EOF)
{
if(c==1){
printf("%lld\n",a);continue;
}
if(c==2){
printf("%lld\n",b);continue;
}
if(c==3){
printf("%lld\n",(a+b)%mod);continue;
}
if(c==4){
printf("%lld\n",(b+a+b-1)%mod);continue;
}
matrix ans;
ans.m[0][0]=b; ans.m[0][1]=a; ans.m[0][2]=1;
ans=mul(ans,pow(r4,(c-2)/4));
ans2=ans.m[0][0]%mod;
ans1=ans.m[0][1]%mod;
for(int i=2+4*((c-2)/4);i<c;i++)
{
tmp=ans2;
ans2+=ans1+si[i%4];
ans2%=mod;
ans1=tmp;
}
printf("%lld\n",((ans2%mod)+mod)%mod);
}
return 0;
}
/**************************************************************
Problem: 1085
User: funer
Language: C++
Result: Accepted
Time:0 ms
Memory:1652 kb
****************************************************************/