题解:
n
n
n很小,最后是一个跟sum有关的
j
j
j次多项式。
维护 s u m a sum^a suma的和即可。 转移矩阵构造可以用拉格朗日插值法。
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int RLEN=1<<18|1;
inline char nc() {
static char ibuf[RLEN],*ib,*ob;
(ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
char ch=nc(); int i=0,f=1;
while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
return i*f;
}
const int N=55, mod=998244353;
inline int add(int x,int y) {return (x+y>=mod) ? (x+y-mod) : (x+y);}
inline int dec(int x,int y) {return (x-y<0) ? (x-y+mod) : (x-y);}
inline int mul(int x,int y) {return (LL)x*y%mod;}
inline int power(int a,int b,int rs=1) {for(;b;b>>=1,a=mul(a,a)) if(b&1) rs=mul(rs,a); return rs;}
inline int cinv(int a) {return power(a,mod-2);}
int n,m;
int s[N];
struct Combin {
int fac[N],ifac[N];
Combin() {
fac[0]=1;
for(int i=1;i<N;i++) fac[i]=mul(fac[i-1],i);
ifac[N-1]=cinv(fac[N-1]);
for(int i=N-2;~i;i--) ifac[i]=mul(ifac[i+1],i+1);
}
inline int C(int a,int b) {return mul(fac[a],mul(ifac[b],ifac[a-b]));}
} C;
struct lgip {
int num[N],yc[N],pre[N],suf[N],deg;
inline void init(int d) {
deg=d+2;
for(int i=1;i<=deg;i++) yc[i]=add(yc[i-1],power(i,d));
for(int i=1;i<=deg;i++) {
num[i]=1;
for(int j=1;j<=deg;j++) if(j!=i) num[i]=mul(num[i],cinv(dec(i,j)));
}
}
inline int getval(int d) {
pre[0]=suf[deg+1]=1;
for(int i=1;i<=deg;i++) pre[i]=mul(pre[i-1],dec(d,i));
for(int i=deg;i>=1;i--) suf[i]=mul(suf[i+1],dec(d,i));
int ans=0;
for(int i=1;i<=deg;i++) ans=add(ans,mul(yc[i],mul(mul(pre[i-1],suf[i+1]),num[i])));
return ans;
}
} f[N];
typedef unsigned long long ULL;
const ULL LIM=ULLONG_MAX-(ULL)mod*mod;
struct matrix {
ULL a[N][N];
matrix(int t=0) {memset(a,0,sizeof(a)); for(int i=0;i<n;++i) a[i][i]=t;}
friend inline matrix operator +(const matrix &a,const matrix &b) {
matrix c(0);
for(int i=0;i<n;i++) for(int j=0;j<n;j++) c.a[i][j]=add(a.a[i][j],b.a[i][j]);
return c;
}
friend inline matrix operator *(const matrix &a,const matrix &b) {
matrix c(0);
for(int i=0;i<n;i++)
for(int k=0;k<n;k++)
for(int j=0;j<n;j++)
((c.a[i][j]+=(ULL)a.a[i][k]*b.a[k][j])>=LIM) ? c.a[i][j]%=mod : 0;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
if(c.a[i][j]>=mod) c.a[i][j]%=mod;
return c;
}
friend inline matrix operator ^(matrix a,int b) {
matrix c(1);
for(;b;b>>=1,a=a*a) if(b&1) c=c*a;
return c;
}
} A,tr;
int main() {
n=rd(), m=rd();
A.a[0][0]=1;
for(int i=0;i<n;i++) f[i].init(i);
for(int i=1;i<=m;i++) {
int a=rd(), b=rd();
static int val[N];
for(int j=0;j<n;j++) val[j]=f[j].getval(b);
for(int j=0;j<n;j++)
for(int k=0;k<=j;k++)
tr.a[k][j]=mul(C.C(j,k),val[j-k]);
A=A*(tr^a);
}
s[0]=1;
for(int i=1;i<=n-1;i++)
for(int j=i;j>=0;j--) {
s[j]=mul(s[j],mod-i);
if(j) s[j]=add(s[j],s[j-1]);
}
for(int i=0;i<=n-1;i++) for(int j=1;j<=n-1;j++) s[i]=mul(s[i],cinv(j));
int ans=0;
for(int j=0;j<=n-1;j++) ans=add(ans,mul(A.a[0][j],s[j]));
cout<<ans<<'\n';
}