题解:AT_abc436_g [ABC436G] Linear Inequation

· · 题解

简单题。

考虑直接列出生成函数。

先对每个数字列出生成函数,即 <1,a_i,2a_i,3a_i,\dots>,等于 \frac{1}{1-x^a_i}

那么记 F(x)=\prod (\dfrac{1}{1-x^{a_i}}),答案就是 \sum_{i=0}^{m} [x^i]F(x)

但是 m 很大,考虑优化。

考虑前缀和的意义,就是 F(x) 与全是 1 的多项式的卷积,那么可化成 [x^k]\frac{1}{(1-x)F(x)},发现是喜闻乐见的 BM 的形式,做完了。

:::info[不熟悉 BM 的看这里]

考虑这样一个问题:求 [x^k]\frac{g(x)}{f(x)}

先同时乘一个 f(-x),变成 [x^k]\frac{g(x)f(-x)}{f(x)f(-x)},考虑 f(x)f(-x) 奇数项全是 0,可写作 H(x^2)

然后令 g(x)f(-x)=F(x^2)+xG(x^2)

原式变成 [x^k](\frac{F(x^2)}{H(x^2)}+\frac{xG(x^2)}{H(x^2)}),前面的只会贡献偶数向,后面的为奇数项,然后由于自变量是 x^2,可除去 2,故结论为:

[x^k]\frac{g(x)}{f(x)}= \begin{cases} [x^{ \frac{k}{2}}]\frac{F(x)}{H(x)} & 2 \mid k\\ \\ [x^{ \frac{k-1}{2}}]\frac{G(x)}{H(x)} & 2\nmid k\\ \end{cases} ::: 代码是好写的。 :::success[code] ```cpp #include<bits/stdc++.h> #define ll long long using namespace std; const int N=(1<<20)+1; mt19937 rnd(time(0)); const int Mod=998244353; inline int mul(int a,int b) { unsigned long long res=1ull*a*b; return res>Mod?res%Mod:res; } inline int add(int a,int b) { a+=b;return a>Mod?a-Mod:a; } inline int ks(int a,int b) { int res=1; while(b) { if(b&1) res=mul(res,a); a=mul(a,a); b>>=1; } return res; } namespace Poly { /* 多项式板子 */ inline int BM(int *f,int n,int *g,int m,ll k) { for(int i=0;i<=n;i++) ar[i]=f[i]; for(int i=0;i<=m;i++) br[i]=g[i]; for(;k;k>>=1) { for(int i=0;i<=m;i++)fz[i]=br[i]; for(int i=1;i<=m;i+=2)fz[i]=Mod-fz[i]; Poly::getmul(ar,n,fz,m,ar); Poly::getmul(br,m,fz,m,br); for(int i=0;i<=m;i++)fz[i]=0; int j=0; for(int i=(k&1);i<=n+m;i+=2,j++)ar[i/2]=ar[i]; for(int i=j;i<=n+m;i++)ar[i]=0;n=j-1,j=0; for(int i=0;i<=2*m;i+=2,j++)br[i/2]=br[i]; for(int i=j;i<=2*m;i++)br[i]=0;m=j-1; } int a0=ar[0],b0=br[0];ar[0]=br[0]=0; return mul(a0,ks(b0,Mod-2)); } } int n; ll m; int la; int a[N],b[N]; signed main() { Poly::prework(); ios::sync_with_stdio(0); cin.tie(0),cout.tie(0); cin>>n>>m;a[0]=1; for(int i=0;i<=n;i++) { int x; if(i==1) x=1; else cin>>x; for(int j=0;j<=la;j++) b[j+x]=Mod-a[j];la+=x; for(int j=0;j<=la;j++) a[j]=add(a[j],b[j]); for(int j=0;j<=la;j++) b[j]=0; } b[0]=1; cout<<Poly::BM(b,0,a,la,m); } ``` :::