【dp,数学】CF1096G Lucky Tickets
我,常数,大。
考虑记给出的可用集合为 \(a\),令 \(f[i][j]\) 为选 \(i\) 个数和为 \(j\) 的方案,则 \(ans=\sum_{i=0}^{5n}f[n/2][i]^2\)。
转移:\(f[i][j]=\sum f[i-1][j-x],x\in a\)
考虑记 \(g[x]=[x\in a]\)
那么,\(f[i][j]=\sum f[i-1][j-x]*g[x]\)
这东西是个卷积的形式,则每次用 NTT 做即可。考虑一共做 \(\dfrac{n}{2}\) 次,则变成多项式快速幂问题。
这里写的是 2log 的倍增,把 #define int long long
去掉后能大大减小常数。
#include <bits/stdc++.h>
using namespace std;
int rd() {
int f=1,sum=0; char ch=getchar();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getchar();}
while(isdigit(ch)) {sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return sum*f;
}
void pr(int x) {
int f=1,tot=0; static int st[30];
if(x<0) x=-x,f=-1;
while(x) st[++tot]=x%10,x/=10;
if(!tot) putchar('0');
else for(int i=tot;i>=1;i--) putchar(st[i]+'0');
}
const int mod=998244353,G=3,INVG=332748118;
int fpow(int x,int y) {
int res=1; x%=mod;
while(y) {
if(y&1) res=res*1ll*x%mod;
y>>=1; x=x*1ll*x%mod;
}
return res;
}
#define N (int)(2e5+5)
int tr[N<<4];
inline void NTT(vector<int>&f,int n,bool fl) {
for(int i=0;i<n;i++) if(i<tr[i]) swap(f[i],f[tr[i]]);
for(int p=2;p<=n;p<<=1) {
int len=(p>>1),w=fpow(fl?G:INVG,(mod-1)/p);
for(int l=0;l<n;l+=p) {
int buf=1;
for(int i=l;i<l+len;i++) {
int qwq=f[i+len]*1ll*buf%mod;
f[i+len]=((f[i]-qwq)%mod+mod)%mod;
f[i]=(f[i]+qwq)%mod;
buf=buf*1ll*w%mod;
}
}
}
if(fl) return ;
int qwq=fpow(n,mod-2);
for(int i=0;i<n;i++) f[i]=f[i]*1ll*qwq%mod;
}
inline vector<int> operator *(vector<int>f,vector<int>g) {
int lef=f.size(),leg=g.size(); int m=1;
while(m<lef+leg-1) m<<=1;
for(int i=0;i<m;i++) tr[i]=(tr[i>>1]>>1)|((i&1)?(m>>1):0);
f.resize(m); g.resize(m);
NTT(f,m,1); NTT(g,m,1);
for(int i=0;i<m;i++) f[i]=f[i]*1ll*g[i]%mod;
NTT(f,m,0); f.resize(lef+leg-1);
return f;
}
inline vector<int> qpow(vector<int>f,int y) {
vector<int>res; res.resize(1);
res[0]=1;
while(y>0) {
if(y&1) res=res*f;
y>>=1; f=f*f;
}
return res;
}
vector<int>f(10);
signed main() {
int n=rd(),m=rd();
for(int i=0;i<10;i++) f[i]=0;
for(int i=1;i<=m;i++) {
int x=rd(); f[x]=1;
}
f=qpow(f,n/2);
int ans=0;
for(int x:f) ans=(ans+x*1ll*x%mod)%mod;
cout<<ans;
return 0;
}