[题解] Codeforces 1548 C The Three Little Pigs 组合数学,生成函数

题目
首先令\(x=i\)时的答案为\(f_i\) ,令\(f_i\)对应的普通生成函数为\(F(x)\)

很容易发现\(F(x)=\sum_{i=0}^n (1+x)^{3i}\),sigma是在枚举第几轮吃(i=0也枚举了,不影响答案), \((1+x)^{3i}\)是在枚举\(3i\)只猪里哪些会被吃。

用等比数列求和公式求出\(F(x)=\frac{(1+x)^{3n+3}-1}{(1+x)^3-1}\)

\(F(x)\)的分子可以用二项式定理暴力展开,分母展开是\(x^3+3x^2+3x\)。由于\(F(x)\)没有无限项,所以暴力做多项式除法是可以除尽的。所以现在就是要暴力计算一个\(3n+3\)次多项式除以一个3次多项式的值,具体做法是从\(3n\)到0枚举每一个次数,然后决定这一项的系数。同时记录当前商和除数的积,则第i位的系数=\((1+x)^{3n+3}-1\)第i+3位的系数-当前商第i位的系数。然后对于询问每次直接输出就行了。时间复杂度\(O(n)\)

点击查看代码
#include <bits/stdc++.h>

#define rep(i,n) for(int i=0;i<n;++i)
#define repn(i,n) for(int i=1;i<=n;++i)
#define LL long long
#define pii pair <LL,LL>
#define fi first
#define se second
#define mpr make_pair
#define pb push_back

using namespace std;

const LL MOD=1e9+7;

LL qpow(LL x,LL a)
{
	LL res=x,ret=1;
	while(a>0)
	{
		if((a&1)==1) ret=ret*res%MOD;
		a>>=1;
		res=res*res%MOD;
	}
	return ret;
}

LL n,q,fac[3000100],inv[3000100],ans[3000100],coef[3000100],cur[3000100];

LL C(LL nn,LL mm){return fac[nn]*inv[mm]%MOD*inv[nn-mm]%MOD;}

int main()
{
  fac[0]=1;repn(i,3000095) fac[i]=fac[i-1]*(LL)i%MOD;
  inv[3000085]=qpow(fac[3000085],MOD-2);
  for(LL i=3000084;i>=0;--i) inv[i]=inv[i+1]*(i+1)%MOD;
  cin>>n;
  rep(i,n*3+4) coef[i]=C(n*3+3,i);
  --coef[0];
  int hi=n*3+3;
  for(int i=hi-3;i>=0;--i)
  {
    LL need=(coef[i+3]-cur[i+3]+MOD)%MOD;
    ans[i]=need;
    (cur[i+3]+=need)%=MOD;
    (cur[i+2]+=need*3LL)%=MOD;
    (cur[i+1]+=need*3LL)%=MOD;
  }
  cin>>q;
  LL x;
  rep(qn,q)
  {
    scanf("%lld",&x);
    printf("%lld\n",ans[x]);
  }
	return 0;
}
posted @ 2022-05-07 14:07  LegendStane  阅读(62)  评论(0)    收藏  举报