hdu 6395 Sequence 分塊矩陣快速冪
阿新 • • 發佈:2019-01-29
容易知道 p/i (i=3......n); 在某一區間內是相同的,記錄前一個區間的fn-1,fn-2,對本區間進行矩陣快速冪,確定本區間的界限可以用一句話 即 j=(p/i)==0?n:min(n,p/(p/i)),並不需要二分;
AC 程式碼
#include <iostream> #include <algorithm> #include <string.h> #include <iostream> #include <map> #include <queue> using namespace std; typedef long long LL; const int maxn=2e5+10; const int mod=1e9+7; const int INF=0x3f3f3f3f; LL a[5][5],b[5][5],res[4][4]; void mul(LL t[5][5],LL t1[5][5]) { memset(res,0,sizeof(res)); for (int i=0;i<3;i++) for (int j=0;j<3;j++) for (int k=0;k<3;k++) res[i][j]=(res[i][j]+t[i][k]*t1[k][j]%mod)%mod; for (int i=0;i<3;i++) for (int j=0;j<3;j++) t[i][j]=res[i][j]; } void quc(LL a[5][5],LL pow) { memset(b,0,sizeof(b)); for (int i=0;i<3;i++) b[i][i]=1; LL temp[5][5]; for (int i=0;i<3;i++) for (int j=0;j<3;j++) temp[i][j]=a[i][j]; while (pow) { if (pow&1) mul(b,temp); mul(temp,temp); pow>>=1; } } int main() { std::ios::sync_with_stdio(false); cin.tie(0);cout.tie(0); int t; cin>>t; while (t--) { int A,B,C,D,p,n; cin>>A>>B>>C>>D>>p>>n; memset(a,0,sizeof(a)); a[0][0]=D;a[0][1]=C;a[0][2]=1; a[1][0]=1;a[2][2]=1; LL f_one,f_sec,fi=B%mod,fj=A%mod; for (int i=3;i<=n;) { LL j=(p/i)==0?n:min(n,p/(p/i)); LL v=p/i; quc(a,j-i+1); f_one=((fi*b[0][0]%mod+fj*b[0][1]%mod)%mod+v*b[0][2]%mod)%mod; f_sec=((fi*b[1][0]%mod+fj*b[1][1]%mod)%mod+v*b[1][2]%mod)%mod; fi=f_one; fj=f_sec; i=j+1; } cout<<fi<<endl; } return 0; }