正题
题目链接:https://ac.nowcoder.com/acm/contest/186/D
题目大意
mmm个二元组(ai,bi)(a_i,b_i)(ai,bi),对于一个序列xxx的贡献是∏i=1n(aixi2+bixi+1)\prod_{i=1}^n(a_ix_i^2+b_ix_i+1)i=1∏n(aixi2+bixi+1)
qqq次询问给出nnn求在xi≥0x_i\geq 0xi≥0且∑i=1nxi=n\sum_{i=1}^nx_i=n∑i=1nxi=n时的情况下所有序列的贡献和。
解题思路
dpdpdp思路
先列出简单的dpdpdp方程fi,j=∑k=0jfi,j−k∗(aik2+bik+1)f_{i,j}=\sum_{k=0}^jf_{i,j-k}*(a_ik^2+b_ik+1)fi,j=k=0∑jfi,j−k∗(aik2+bik+1)
然后发现这个每次转移时加的值是∑k=0jfi,j−k∗(2aik+ai+bi)\sum_{k=0}^jf_{i,j-k}*(2a_ik+a_i+b_i)k=0∑jfi,j−k∗(2aik+ai+bi)
然后这个加的值每次转移时加的值是∑k=0jfi,j−k∗2ai\sum_{k=0}^jf_{i,j-k}*2a_ik=0∑jfi,j−k∗2ai
开几个差分变量统计即可。
时间复杂度O(nm+q)O(nm+q)O(nm+q)
OGFOGFOGF思路
阿巴阿巴这个我一点都不会,大部分都是靠幂炜大爷的指点的
每个物品是一个∑i≥0xi(ai2+bi+1)\sum_{i\geq 0}x^i(ai^2+bi+1)∑i≥0xi(ai2+bi+1)的一个生成函数,然后化一下
a∑i≥0xii2+b∑i≥0xii+∑i≥0xia\sum_{i\geq 0}x^ii^2+b\sum_{i\geq 0}x^ii+\sum_{i\geq 0}x^iai≥0∑xii2+bi≥0∑xii+i≥0∑xi
最后一个是11−x\frac{1}{1-x}1−x1就不多解释了,化一下前面两个
S=∑i≥0xii2,xS=∑i≥1xi+1i2S=\sum_{i\geq 0}x^ii^2,xS=\sum_{i\geq 1}x^{i+1}i^2S=i≥0∑xii2,xS=i≥1∑xi+1i2
(1−x)S=∑i≥1xi(i2−(i−1)2)=2∗∑i≥1xii−∑i≥0xi(1-x)S=\sum_{i\geq 1}x^{i}(\ i^2-(i-1)^2\ )=2*\sum_{i\geq 1}x^i i-\sum_{i\geq 0}x^i(1−x)S=i≥1∑xi( i2−(i−1)2 )=2∗i≥1∑xii−i≥0∑xi
然后前面那个我们同理T=∑i≥0xii,xT=∑i≥1xi+1iT=\sum_{i\geq 0}x^ii,xT=\sum_{i\geq 1}x^{i+1}iT=i≥0∑xii,xT=i≥1∑xi+1i
(1−x)T=∑i≥1xi=x1−x,T=x(1−x)2(1-x)T=\sum_{i\geq 1}x^{i}=\frac{x}{1-x},T=\frac{x}{(1-x)^2}(1−x)T=i≥1∑xi=1−xx,T=(1−x)2x
代回去
(1−x)S=2x(1−x)2−x(1−x)=2x−x(1−x)(1−x)2=x(x+1)(1−x)2(1-x)S=\frac{2x}{(1-x)^2}-\frac{x}{(1-x)}=\frac{2x-x(1-x)}{(1-x)^2}=\frac{x(x+1)}{(1-x)^2}(1−x)S=(1−x)22x−(1−x)x=(1−x)22x−x(1−x)=(1−x)2x(x+1)
S=∑i≥0xii2=x(x+1)(1−x)3,∑i≥0xii=1(1−x)2S=\sum_{i\geq 0}x^ii^2=\frac{x(x+1)}{(1-x)^3}\ \ ,\ \ \ \sum_{i\geq 0}x_ii=\frac{1}{(1-x)^2}S=i≥0∑xii2=(1−x)3x(x+1) , i≥0∑xii=(1−x)21
之前那个式子就可以变成
ax(x+1)(1−x)3+bx(1−x)2+11−x\frac{ax(x+1)}{(1-x)^3}+\frac{bx}{(1-x)^2}+\frac{1}{1-x}(1−x)3ax(x+1)+(1−x)2bx+1−x1
然后展开就成了
1+(a+b−2)x+(a−b+1)x2(1−x)3\frac {1+(a+b-2)x+(a-b+1)x^2}{(1-x)^{3}}(1−x)31+(a+b−2)x+(a−b+1)x2
然后所有的乘起来,因为只有三个系数,所以可以暴力乘。
答案就是乘积的生成函数中xnx^nxn的系数,考虑如何求。
我们已经处理出了一个fff数组,∑j≥0xifi(1−x)3m\frac{\sum_{j\geq 0}x^if_i}{(1-x)^{3m}}(1−x)3m∑j≥0xifi有
1(1−x)k=(∑i≥0xi)k=∑i≥0xi(k+i−1i−1)\frac{1}{(1-x)^k}=(\sum_{i\geq 0}x^i)^k=\sum_{i\geq 0}x^i\binom{k+i-1}{i-1}(1−x)k1=(i≥0∑xi)k=i≥0∑xi(i−1k+i−1)
∑j≥0xifi(1−x)3m=∑j≥0xifi∗∑i≥0xi(3m+i−1i−1)\frac{\sum_{j\geq 0}x^if_i}{(1-x)^{3m}}=\sum_{j\geq 0}x^if_i*\sum_{i\geq 0}x^i\binom{3m+i-1}{i-1}(1−x)3m∑j≥0xifi=j≥0∑xifi∗i≥0∑xi(i−13m+i−1)
然后就可以卷积了,xnx_nxn的系数就是
∑i=0nfn−i(3m+i−1i−1)\sum_{i=0}^nf_{n-i}\binom{3m+i-1}{i-1}i=0∑nfn−i(i−13m+i−1)
时间复杂度O((q+m)n)O(\ (q+m)n\ )O( (q+m)n )
codecodecode
dpcodedp\ \ codedp code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1100,XJQ=998244353;
ll m,q,n,a[N],b[N],f[N][11000];
int main()
{scanf("%lld",&m);f[0][0]=1;for(ll i=1;i<=m;i++){scanf("%lld%lld",&a[i],&b[i]);ll tmp1=0,tmp2=0,tmp3=0,sum=0;for(ll j=0;j<1e4;j++){sum=(sum+tmp2+tmp3+f[i-1][j])%XJQ;f[i][j]=sum;tmp2=(tmp2+tmp1)%XJQ;tmp1=(tmp1+2*f[i-1][j]%XJQ*a[i]%XJQ)%XJQ;tmp3=(tmp3+(b[i]+a[i])*f[i-1][j])%XJQ;}}scanf("%lld",&q);while(q--){scanf("%lld",&n);printf("%lld\n",f[m][n]);}return 0;
}
OGFcodeOGF\ \ codeOGF code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=4e4+10,P=998244353;
ll n,m,q,tot,fac[N],inv[N],f[N];
ll C(ll n,ll m)
{return fac[n]*inv[m]%P*inv[n-m]%P;}
int main()
{scanf("%lld",&m);inv[1]=f[0]=fac[0]=inv[0]=1;for(ll i=2;i<=4e4;i++)inv[i]=(P-P/i)*inv[P%i]%P;for(ll i=1;i<=4e4;i++)fac[i]=fac[i-1]*i%P,inv[i]=inv[i-1]*inv[i]%P; for(ll i=1;i<=m;i++){ll a,b;scanf("%lld%lld",&a,&b);ll A=(a-b+1+P)%P,B=(a+b-2+P)%P;tot+=3;for(ll j=1e4;j>=0;j--){if(j>1)(f[j]+=f[j-2]*A%P)%=P;if(j>0)(f[j]+=f[j-1]*B%P)%=P;}}scanf("%lld",&q);while(q--){scanf("%lld",&n);ll ans=0;for(ll i=0;i<=n;i++)(ans+=C(i+tot-1,tot-1)*f[n-i]%P)%=P;printf("%lld\n",ans);}return 0;
}