ARC061D 题解
先进行一个模型转换:要求满足以下条件的字符串数量:
- 由
a
、b
、c
三种字符组成。 - 其中恰好有 $n$ 个
a
,且以a
结尾。 b
不超过 $m$ 张,c
不超过 $k$ 张。
思考转换的过程:每个字符对应抽到的卡牌。其中第二条保证了 a
会胜利,第三条保证了这个过程中 b
或 c
不会出现已经赢了的情况。
那么有:$$ \text{ans}=\sum_{t=0}^{m+k} (C_{t+n-1}^{n-1}\times(\sum_{x=t-k}^{m} C_{t}^{x})\times 3^{m+k-t}) $$ 设:$$ f(t)=\sum_{x=t-k}^{m} C_{t}^{x} $$ 则:$$ \begin{aligned} f(t)&=\sum_{x=t-k}^{m} (C_{t-1}^{x}+C_{t-1}^{x-1}) \\ &=(\sum_{x=t-k}^{m}C_{t-1}^{x})+(\sum_{x=t-k}^{m}C_{t-1}^{x-1}) \\ &=(\sum_{x=t-k}^{m}C_{t-1}^{x})+(\sum_{x=t-k-1}^{m-1}C_{t-1}^{x}) \\ &=(f(t-1)-C_{t-1}^{t-k-1})+(f(t-1)-C_{t-1}^{m}) \\ &=2 \times f(t-1)-C_{t-1}^{t-k-1}-C_{t-1}^{m} \end{aligned} $$ 发现现在可以在 $O(n \log {10^9+7})$ 的复杂度递推求出 $f(t)$。我们把 $f(t)$ 带入原式:$$ \text{ans}=\sum_{t=0}^{m+k} (C_{t+n-1}^{n-1}\times f(t)\times 3^{m+k-t}) $$
当然,用来算组合数的逆元以及 $3$ 的幂次可以线性预处理,这样时间复杂度降为线性。
#include <bits/stdc++.h>
#define L(i, a, b) for(int i = a; i <= b; i++)
#define R(i, a, b) for(int i = a; i >= b; i--)
using namespace std;
const int N = 3e5 + 10, mod = 1e9 + 7;
int n, m, k, fac[N * 3], f[N * 2], ans;
int qpow(int a, int b){
int ans = 1;
while(b){
if(b & 1) ans = 1ll * ans * a % mod;
a = 1ll * a * a % mod, b >>= 1;
}
return ans;
}
int inv(int x){return qpow(x, mod - 2);}
int C(int n, int m){
if(m < 0 || m > n) return 0;
return 1ll * fac[n] * inv(fac[m]) % mod * inv(fac[n - m]) % mod;
}
int main(){
scanf("%d%d%d", &n, &m, &k); fac[0] = f[0] = 1;
L(i, 1, n + m + k) fac[i] = 1ll * fac[i - 1] * i % mod;
L(i, 1, m + k) f[i] = (2ll * f[i - 1] - C(i - 1, i - k - 1) - C(i - 1, m) + mod * 2) % mod;
L(i, 0, m + k) (ans += 1ll * C(i + n - 1, n - 1) * f[i] % mod * qpow(3, m + k - i) % mod) %= mod;
printf("%d\n", ans);
return 0;
}