CF1106F Lunar New Year and a Recursive Sequence - 矩陣快速冪、數論
阿新 • • 發佈:2021-07-01
題解
第一次不看 editorial 做出來 CF 難度 \(2400\) 的題!!!
這個推 \(f_i\) 的式子一看就很像矩陣加速,但它裡面是乘號。於是我們考慮維護每個 \(f_i\) 裡面含有多少個 \(f_1,f_2,\dots,f_k\)。
記 \(f_{i,j}\) 為 \(f_i\) 裡面含有的 \(f_j(1\le j\le k)\) 個數。於是可以構造轉移矩陣:
\[\begin{bmatrix} f_{n,1} & f_{n,2} & \dots & f_{n,k} \\ f_{n+1,1} & f_{n+1,2} & \dots & f_{n+1,k} \\ \vdots & \vdots & \vdots & \vdots \\ f_{n+k-1,1} & f_{n+k-1,2} & \dots & f_{n+k-1,k} \end{bmatrix}=\begin{bmatrix} 0 & 1 & 0 & 0 & \dots & 0 \\ 0 & 0 & 1 & 0 & \dots & 0 \\ \vdots & \vdots & \vdots &\vdots &\vdots &\vdots \\ b_k & b_{k-1} & b_{k-2} & b_{k-3} & \dots & b_1 \end{bmatrix} \times \begin{bmatrix} f_{n-1,1} & f_{n-1,2} & \dots & f_{n-1,k} \\ f_{n,1} & f_{n,2} & \dots & f_{n,k} \\ \vdots & \vdots & \vdots & \vdots \\ f_{n+k-2,1} & f_{n+k-2,2} & \dots & f_{n+k-2,k} \end{bmatrix} \]矩陣快速冪完了,取第 \(1\)
程式碼出人意料地短。
程式碼
#include <cstdio> #include <cstring> #include <cctype> #include <map> #include <cmath> using namespace std; #define For(Ti,Ta,Tb) for(int Ti=(Ta);Ti<=(Tb);++Ti) #define Dec(Ti,Ta,Tb) for(int Ti=(Ta);Ti>=(Tb);--Ti) template<typename T> void Read(T &x){ x=0;int _f=1; char ch=getchar(); while(!isdigit(ch)) _f=(ch=='-'?-1:_f),ch=getchar(); while(isdigit(ch)) x=x*10+(ch^48),ch=getchar(); x=x*_f; } template<typename T,typename... Args> void Read(T &x,Args& ...others){ Read(x);Read(others...); } typedef long long ll; const int K=105,Mod=998244353,Root=3; typedef ll Mat[K][K]; int len; void MatMul(Mat &c,const Mat &a,const Mat &b){ Mat res;memset(res,0,sizeof res); For(k,1,len) For(i,1,len) For(j,1,len){ res[i][j]=(res[i][j]+a[i][k]*b[k][j])%(Mod-1); }memcpy(c,res,sizeof res); } void MatPow(Mat &c,const Mat &x,ll b){ Mat res,a; memset(res,0,sizeof res);memcpy(a,x,sizeof x); For(i,1,len) res[i][i]=1; while(b){ if(b&1) MatMul(res,res,a); b>>=1,MatMul(a,a,a); }memcpy(c,res,sizeof res); } ll Pow(ll a,ll b,ll p){ ll res=1; while(b){ if(b&1) res=res*a%p; b>>=1,a=a*a%p; }return res; } ll BSGS(ll a,ll b,ll p){//a^x=b(mod p) map<ll,int> mp; ll t=ceil(sqrt(p+.5)); for(ll cur=1,x=0;x<=t;++x,cur=cur*a%p){ mp[cur*b%p]=x; } ll temp=Pow(a,t,p); for(ll cur=temp,x=1;x<=t;++x,cur=cur*temp%p){ if(mp.count(cur)) return x*t-mp[cur]; }return -1; } int n;ll b[K],m;Mat mat; int main(){ Read(len);For(i,1,len) Read(b[i]); Read(n,m); For(i,1,len-1) mat[i][i+1]=1; For(j,1,len) mat[len][j]=b[len-j+1]; MatPow(mat,mat,n-1); ll a=mat[1][len]; ll res=BSGS(Pow(Root,a,Mod),m,Mod); if(res==-1) return puts("-1"),0; printf("%lld\n",Pow(Root,res,Mod)); return 0; }