CF1548C The Three Little Pigs
https://www.luogu.com.cn/problem/CF1548C
VP到这题的时候卡了一会
有两种做法:
可以是道生成函数入门题
实际上要求的是对于一个x,求
∑
i
=
1
n
(
3
i
m
)
\sum_{i=1}^n\binom{3i}{m}
i=1∑n(m3i)
这个鬼东西一看就很生成函数
可以表示为
[
x
m
]
∑
i
=
1
n
(
1
+
x
)
3
i
[x^m]\sum_{i=1}^n(1+x)^{3i}
[xm]i=1∑n(1+x)3i
按照套路化简最后变成
(
1
+
x
)
3
i
+
3
−
(
1
+
x
)
3
(
1
+
x
)
3
−
1
\frac{(1+x)^{3i+3}-(1+x)^3}{(1+x)^3-1}
(1+x)3−1(1+x)3i+3−(1+x)3
上面那个直接用组合数算,然后大力多项式除法即可
也可以是玄妙DP
把
3
i
,
3
i
+
1
,
3
i
+
2
3i,3i+1,3i+2
3i,3i+1,3i+2分在一起,看他们之间的关系
可以设
f
[
i
]
[
k
]
=
∑
i
=
0
n
−
1
(
3
i
+
k
x
)
f[i][k]=\sum_{i=0}^{n-1}\binom{3i+k}{x}
f[i][k]=i=0∑n−1(x3i+k)
答案就是
f
[
n
]
[
0
]
f[n][0]
f[n][0]
通过上指标求和可以得到
f
[
i
]
[
0
]
+
f
[
i
]
[
1
]
+
f
[
i
]
[
2
]
=
∑
i
=
0
3
n
−
1
(
i
x
)
=
(
3
n
x
+
1
)
f[i][0]+f[i][1]+f[i][2]=\sum_{i=0}^{3n-1}\binom{i}{x}=\binom{3n}{x+1}
f[i][0]+f[i][1]+f[i][2]=i=0∑3n−1(xi)=(x+13n)
由组合数的转移式又可以得到
f
[
i
]
[
1
]
=
f
[
i
]
[
0
]
+
f
[
i
−
1
]
[
0
]
f
[
i
]
[
2
]
=
f
[
i
]
[
1
]
+
f
[
i
−
1
]
[
1
]
f[i][1]=f[i][0]+f[i-1][0]\\ ~~ \\f[i][2]=f[i][1]+f[i-1][1]
f[i][1]=f[i][0]+f[i−1][0] f[i][2]=f[i][1]+f[i−1][1]
然后用这三条式子就可以解出递推式了
code(生成函数):
#include<bits/stdc++.h>
#define ll long long
#define N 3000050
#define mod 1000000007
#define int long long
using namespace std;
int qpow(int x, int y) {
int ret = 1;
for(; y; y >>= 1, x = 1ll * x * x % mod) if(y & 1) ret = 1ll * ret * x % mod;
return ret;
}
int fac[N], ifac[N];
void init(int n) {
fac[0] = 1;
for(int i = 1; i <= n; i ++) fac[i] = 1ll * fac[i - 1] * i % mod;
ifac[n] = qpow(fac[n], mod - 2);
for(int i = n - 1; i >= 0; i --) ifac[i] = 1ll * ifac[i + 1] * (i + 1) % mod;
}
int C(int n, int m) {
return 1ll * fac[n] * ifac[n - m] % mod * ifac[m] % mod;
}
int n, q;
ll a[N], f[N];
signed main() {
scanf("%lld%lld", &n, &q);
init(3 * n + 3);
for(int i = 0; i <= 3 * n + 3; i ++) a[i] = C(3 * n + 3, i);
// for(int i = 0; i <= 3 * n + 3; i ++) printf("%lld ", a[i]); printf("\n");
a[0] --; a[0] = (a[0] + mod) % mod; a[1] = (a[1] - 3 + mod) % mod; a[2] = (a[2] - 3 + mod) % mod, a[3] = (a[3] - 1 + mod) % mod;
for(int i = 3 * n + 3; i >= 3; i --) {
f[i - 3] = a[i];
a[i - 1] = (a[i - 1] - a[i] * 3 + 10ll * mod) % mod;
a[i - 2] = (a[i - 2] - a[i] * 3 + 10ll * mod) % mod;
}
while(q --) {
int x; scanf("%lld", &x);
printf("%lld\n", f[x]);
}
return 0;
}