HDU6395 Sequence 2018多校聯合第七場 代常數矩陣快速冪+分段思維
阿新 • • 發佈:2019-01-29
這道題emmmmmmn...
比賽的時候想到矩陣快速冪了,但分段這個真的是...不好想更不好敲。。後來看了標程,豁然開朗Orz
只能說明。。我好菜啊啊啊啊啊555555...
遞推式如下:(x是不斷更新的量)
| f(n) | | D C x | | f(n-1) |
| f(n-1) | = | 1 0 0 | * | f(n-2) |
| 1 | | 0 0 1 | |
有個bug就是矩陣相乘的時候順序反了,一般矩陣是不滿足交換律的,所以一定要注意。
附上AC程式碼:
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<ctime> #include<algorithm> using namespace std; #define ll long long const ll MOD=1e9+7; ll A,B,C,D,P,n; struct mat { ll a[3][3]; }c,ans,unit; mat mul(mat x,mat y,ll n)//注意x,y的順序!!! { mat cnt; memset(cnt.a,0,sizeof(cnt.a)); for(ll i=0;i<n;i++) for(ll j=0;j<n;j++) for(ll k=0;k<n;k++) cnt.a[i][j]=(cnt.a[i][j]+x.a[i][k]*y.a[k][j]%MOD)%MOD; return cnt; } mat Pow(mat c,ll k) { mat res; memcpy(res.a,unit.a,sizeof(res.a)); while(k>0) { if(k&1) res=mul(res,c,3); c=mul(c,c,3); k=(k>>1); } return res; } void init(ll x) { c.a[0][0]=D;c.a[0][1]=C;c.a[0][2]=x; c.a[1][0]=1;c.a[1][1]=0;c.a[1][2]=0; c.a[2][0]=0;c.a[2][1]=0;c.a[2][2]=1; return; } int main() { memset(unit.a,0,sizeof(unit.a)); for(int i=0;i<3;i++) unit.a[i][i]=1; int T; scanf("%d",&T); while(T--) { scanf("%lld%lld%lld%lld%lld%lld",&A,&B,&C,&D,&P,&n); if(n==1) printf("%lld\n",A); else if(n==2) printf("%lld\n",B); else if(n<P) { ans=unit; for(ll i=3;i<=n;i=P/(P/i)+1) { init(P/i); if(n<=P/(P/i)) c=Pow(c,n-i+1); else c=Pow(c,P/(P/i)+1-i); ans=mul(c,ans,3); } ll aans=(ans.a[0][0]*B%MOD+ans.a[0][1]*A%MOD+ans.a[0][2]%MOD)%MOD; cout<<aans<<endl; } else if(P<=n) { ans=unit; for(ll i=3;i<=P;i=P/(P/i)+1) { init(P/i); c=Pow(c,P/(P/i)+1-i); ans=mul(c,ans,3); } init(0); c=Pow(c,n-max(P,(ll)2)); ans=mul(c,ans,3); ll aans=(ans.a[0][0]*B%MOD+ans.a[0][1]*A%MOD+ans.a[0][2]%MOD)%MOD; cout<<aans<<endl; } } return 0; }