Luogu P4723 模板常系数齐次线性递推
Posted wwwsfff
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu P4723 模板常系数齐次线性递推相关的知识,希望对你有一定的参考价值。
看了一下午的特征多项式,仍然不晓得特征多项式
所以看了BJ大神的博客后恍然大悟
答案相当于求\\(x^n\\),发现可以写作\\(x^n-a_1 x^{n-1}-a_2 x^{n-2}\\cdots\\)可以像小学生一样尝试消元,这便是多项式取模
最后乘起来加起来即可
EI队长的优化估计这辈子都不会去填坑了
#include<bits/stdc++.h>
#define ll long long
const int p=998244353,G=3;
using namespace std;
const int N=4e5+5;
int n,m,gi,f[N],g[N],a[N],h[N],len,rf[N];
int mo(int x) {
return x>=p?x-p:x;
}
int ksm(ll a,int b) {
ll ret=1;
while(b) {
if(b&1) ret=ret*a%p;
a=a*a%p,b>>=1;
}
return ret;
}
void ntt(int *a,int len,int op) {
static int R[N];
for(int i=0;i<len;i++) {
R[i]=(R[i>>1]>>1);
if(i&1) R[i]|=(len>>1);
if(R[i]>i) swap(a[R[i]],a[i]);
}
for(int i=1;i<len;i<<=1){
int Wn=ksm(op==1?G:gi,(p-1)/(i<<1));
for(int j=0;j<len;j+=(i<<1)) {
ll w=1;
for(int k=j;k<j+i;k++) {
int t=w*a[k+i]%p;
a[k+i]=mo(a[k]+p-t);
a[k]=mo(a[k]+t);
w=w*Wn%p;
}
}
}
if(op==-1) {
int t=ksm(len,p-2);
for(int i=0;i<len;i++) a[i]=(ll)a[i]*t%p;
}
}
void getinv(int *a,int len,int *b) {
static int c[N];
if(len==1) {
b[0]=ksm(a[0],p-2);
b[1]=0;
return;
}
getinv(a,len>>1,b);
for(int i=0;i<len;i++) c[i]=a[i];
fill(b+len,b+(len<<1),0);
fill(c+len,c+(len<<1),0);
ntt(c,len<<1,1),ntt(b,len<<1,1);
for(int i=0;i<(len<<1);i++) b[i]=(ll)b[i]*(p+2-(ll)c[i]*b[i]%p)%p;
ntt(b,len<<1,-1);
fill(b+len,b+(len<<1),0);
}
void mod(int *a) {
static int t[N],q[N];
int l=(m<<1)-2; while(a[l]==0) --l; l++;
if(l<=m) return;
memcpy(t,a,sizeof(t));
reverse(t,t+l);
fill(t+l-m,t+l,0);
ntt(t,len<<1,1);
for(int i=0;i<(len<<1);i++) q[i]=(ll)t[i]*rf[i]%p;
ntt(q,len<<1,-1);
fill(q+l-m,q+(len<<1),0);
reverse(q,q+l-m);
ntt(q,len<<1,1);
for(int i=0;i<(len<<1);i++) q[i]=(ll)q[i]*f[i]%p;
ntt(q,len<<1,-1);
for(int i=0;i<m;i++) a[i]=mo(a[i]+p-q[i]);
fill(a+m,a+l,0);
}
void Ksm(int* A,int b,int *C) {
C[0]=1;
while(b){
if(b&1) {
ntt(A,len<<1,1),ntt(C,len<<1,1);
for(int i=0;i<(len<<1);i++) {
C[i]=(ll)C[i]*A[i]%p;
A[i]=(ll)A[i]*A[i]%p;
}
ntt(A,len<<1,-1),ntt(C,len<<1,-1);
mod(A),mod(C);
} else {
ntt(A,len<<1,1);
for(int i=0;i<(len<<1);i++) A[i]=(ll)A[i]*A[i]%p;
ntt(A,len<<1,-1);
mod(A);
}
b>>=1;
}
}
int tmp[N];
int main() {
gi=ksm(G,p-2);
scanf("%d%d",&n,&m);
for(len=1;len<=m;len<<=1);
for(int i=1;i<=m;i++) {
scanf("%d",&f[m-i]),f[m-i]=mo(p-f[m-i]%p);
}
f[m]=1;
memcpy(rf,f,sizeof(f));
ntt(f,len<<1,1);
reverse(rf,rf+m+1);
memcpy(tmp,rf,sizeof(rf));
getinv(tmp,len,rf);
ntt(rf,len<<1,1);
for(int i=0;i<m;i++) {
scanf("%d",&a[i]),a[i]=mo(a[i]%p+p);
}
g[1]=1;
Ksm(g,n,h);
int ans=0;
for(int i=0;i<m;i++) ans=(ans+(ll)a[i]*h[i])%p;
cout<<ans<<endl;
return 0;
}
以上是关于Luogu P4723 模板常系数齐次线性递推的主要内容,如果未能解决你的问题,请参考以下文章