dutacm.club_1085_Water Problem_(矩阵快速幂)
1085: Water Problem
Time Limit:3000/1000 MS (Java/Others) Memory Limit:163840/131072 KB (Java/Others)
Total Submissions:1252 Accepted:132
[Submit][Status][Discuss]Total Submissions:1252 Accepted:132
Description
函数 f:Z+→Z。已知 f(1),f(2) 的值,且对于任意 x>1x>1,有 f(x+1)=f(x)+f(x−1)+sin(πx/2)。
求 f(n)f(n) 的值。
Input
多组数据。(数据组数 T≤100)
每组数据包含 3 个不超过 10^9 的正整数,分别代表 f(1),f(2)和 n 的值。
Output
输出 f(n)mod(10^9+7)。每组输出末尾有换行符。
Sample Input
1 2 3
1 2 5
Sample Output
3 7
题意很清楚。题目出处:http://dutacm.club:7217/codesheaven/problem.php?id=1085
思路:也是看的题解,之前就是最后的sin解决不了。使用此处sin函数的周期为4,那么每半个周期可以将sin抵消掉。
f(x+1)=f(x)+f(x-1)+sin(πx/2) 1式
f(x-1)=f(x-2)+f(x-3)+sin(π(x-2)/2) 2式
将2式带入1式,得f(x+1)=f(x)+f(x-2)+f(x-3),然后转移矩阵很容易写出。
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<algorithm> #include<string> using namespace std; #define MOD 1000000007 #define LL long long int Sin[4]= {0,1,0,-1}; struct Matrix { int row,col; LL matr[8][8]; Matrix() {} Matrix(int r,int c,int num=0) { row=r; col=c; for(int i=1; i<=r; i++) for(int j=1; j<=c; j++) matr[i][j]=num; } }; Matrix matr_multi(Matrix m1,Matrix m2) //矩阵乘法 { Matrix m3(m1.row,m2.col,0); for(int i=1; i<=m1.row; i++) for(int j=1; j<=m2.col; j++) for(int k=1; k<=m1.col; k++) m3.matr[i][j]=(m3.matr[i][j]+m1.matr[i][k]*m2.matr[k][j])%MOD; return m3; } void matr_givevalue(Matrix& a,Matrix b) { a.row=b.row; a.col=b.col; for(int i=1; i<=a.row; i++) for(int j=1; j<=a.col; j++) a.matr[i][j]=b.matr[i][j]; } Matrix matr_pow(Matrix m1,int k) //矩阵快速幂 { Matrix m2; matr_givevalue(m2,m1); k--; while(k>0) { if(k&1) m2=matr_multi(m2,m1); m1=matr_multi(m1,m1); k>>=1; } return m2; } LL PowMod(LL n,int k) //常规快速幂 { LL res=1; while(k>0) { if(k&1) res=(res*n)%MOD; n=(n*n)%MOD; k>>=1; } return res; } void matr_output(Matrix m) { for(int i=1; i<=m.row; i++) { for(int j=1; j<=m.col; j++) cout<<m.matr[i][j]<<" "; cout<<endl; } } int main() { LL f1,f2,n; while(scanf("%lld%lld%lld",&f1,&f2,&n)!=EOF) { Matrix m1(1,4); m1.matr[1][4]=f1; m1.matr[1][3]=f2; m1.matr[1][2]=(f1+f2+Sin[2])%MOD; m1.matr[1][1]=(m1.matr[1][2]+m1.matr[1][3]+Sin[3])%MOD; Matrix m2(4,4,0); m2.matr[1][1]=m2.matr[1][2]=m2.matr[2][3]=m2.matr[3][1]=1; m2.matr[3][4]=m2.matr[4][1]=1; if(n>4) { m2=matr_pow(m2,n-4); m1=matr_multi(m1,m2); printf("%lld\n",m1.matr[1][1]); } else { printf("%lld\n",m1.matr[1][5-n]); } } return 0; }