【CF1548C】The Three Little Pigs
题目
题目链接:https://codeforces.com/contest/1548/problem/C
给定 \(n,Q\),\(Q\) 次询问,每次询问给出 \(k\),求
\[\sum^{n}_{i=1}\binom{3i}{k}\bmod 10^9+7
\]
\(n\leq 10^6,Q\leq 2\times 10^5\)。
思路
设 \(f[i][j]=\sum^{n-1}_{k=0}\binom{3k+j}{i}\bmod 10^9+7\) 的值。其中 \(j\in [0,2]\)。这样的话,答案就是 \(f[k][0]+\binom{3n}{k}\) 了。
考虑怎么转移。根据 \(\binom{n}{m}=\binom{n-1}{m}+\binom{n-1}{m-1}\),有
\[f[i][1]=f[i][0]+f[i-1][0]
\]
\[f[i][2]=f[i][1]+f[i-1][1]
\]
然后观察到
\[f[i][0]+f[i][1]+f[i][2]=\sum^{3n-1}_{j=0}\binom{j}{i}=\binom{3n}{i+1}
\]
就可以进行 dp 预处理出 \(f[i][j]\) 了。
至于 \(\sum^{3n-1}_{j=0}\binom{j}{i}=\binom{3n}{i+1}\) 的原因,考虑组合意义,“从 \(3n\) 个物品选出 \(i+1\) 个”。当最后一个被选择的物品是第 \(k\) 个时,方案数就等于 \(\binom{k-1}{i}\)。
时间复杂度 \(O(n+Q)\)。
代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3000010,MOD=1e9+7,inv3=333333336;
int n,Q,f[N][3];
ll fac[N],inv[N];
ll fpow(ll x,ll k)
{
ll ans=1;
for (;k;k>>=1,x=x*x%MOD)
if (k&1) ans=ans*x%MOD;
return ans;
}
ll C(int n,int m)
{
if (n<m) return 0;
return fac[n]*inv[m]%MOD*inv[n-m]%MOD;
}
int main()
{
scanf("%d%d",&n,&Q);
fac[0]=inv[0]=1;
for (int i=1;i<=3*n;i++) fac[i]=fac[i-1]*i%MOD;
inv[3*n]=fpow(fac[3*n],MOD-2);
for (int i=3*n-1;i>=1;i--) inv[i]=inv[i+1]*(i+1)%MOD;
f[0][0]=f[0][1]=f[0][2]=n;
for (int i=1;i<=3*n;i++)
{
f[i][0]=(C(3*n,i+1)-f[i-1][1]-f[i-1][0]*2)*inv3%MOD;
f[i][1]=(f[i][0]+f[i-1][0])%MOD;
f[i][2]=(f[i][1]+f[i-1][1])%MOD;
}
while (Q--)
{
int k;
scanf("%d",&k);
cout<<((f[k][0]+C(3*n,k))%MOD+MOD)%MOD<<"\n";
}
return 0;
}