Description
,输出
Solution
- 完全没有想到可以直接将组合数用多项式表示,来推式子,经典姿势++
- 原式的系数显然是
- 这个式子看起来不好求,我们把它转化一下
- 因为是点乘,相当于是点乘,即:
- 先卷积算出出点积的结果,再带回去卷积一次即可。
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#define maxn 3000005
#define ll long long
#define uint unsigned int
#define mo 998244353
using namespace std;
int n,m,i,j,k,lim,bt[maxn];
ll A[maxn],S,M,B,fct[maxn],invf[maxn],_2[maxn];
ll a[maxn],b[maxn],c[maxn];
ll ksm(ll x,ll y){
ll s=1;
for(;y;y/=2,x=x*x%mo) if (y&1)
s=s*x%mo;
return s;
}
void dft(ll *a,int sig){
for(int i=0;i<lim;i++) if (i<bt[i]) swap(a[i],a[bt[i]]);
for(int mid=1;mid<lim;mid<<=1){
ll gn=ksm(3,(mo-1)/(mid<<1));
if (sig<0) gn=ksm(gn,mo-2);
for(int j=0;j<lim;j+=mid<<1){
ll g=1;
for(int k=0;k<mid;k++,g=g*gn%mo){
ll x=a[j+k],y=a[j+k+mid]*g;
a[j+k]=(x+y)%mo,a[j+k+mid]=(x-y)%mo;
}
}
}
}
int main(){
freopen("count.in","r",stdin);
freopen("count.out","w",stdout);
scanf("%d%lld%lld%lld%lld",&n,&A[0],&S,&M,&B);
for(i=1;i<=n;i++) A[i]=((A[i-1]^S)*M+B)%mo;
fct[0]=1;for(i=1;i<=n;i++) fct[i]=fct[i-1]*i%mo;
_2[0]=1;for(i=1;i<=n;i++) _2[i]=_2[i-1]*2%mo;
invf[n]=ksm(fct[n],mo-2);
for(i=n-1;i>=0;i--) invf[i]=invf[i+1]*(i+1)%mo;
for(lim=1;lim<=2*n;lim<<=1);
for(i=1;i<lim;i++) bt[i]=(bt[i>>1]>>1)|((i&1)?(lim>>1):0);
for(i=0;i<=n;i++) a[i]=invf[i],b[i]=invf[i]*A[i]%mo;
dft(a,1),dft(b,1);
for(i=0;i<lim;i++) c[i]=a[i]*b[i]%mo;
dft(c,-1);
ll inv=ksm(lim,mo-2);
for(i=0;i<=n;i++) c[i]=c[i]*inv%mo*fct[i]%mo;
memset(a,0,sizeof(a)),memset(b,0,sizeof(b));
for(i=0;i<=n;i++) a[i]=_2[i]*invf[i]%mo*c[n-i]%mo,b[i]=invf[i]*((i&1)?-1:1);
dft(a,1),dft(b,1);
for(i=0;i<lim;i++) c[i]=a[i]*b[i]%mo;
dft(c,-1);
inv=ksm(lim,mo-2);
uint ans=0,mul=1,p=1e9+7;
for(i=0;i<=n;i++,mul=mul*p) {
c[i]=(c[i]*inv%mo*fct[i]%mo+mo)%mo;
ans+=mul*c[i];
}
printf("%u",ans);
}