专栏文章
题解:P11655 「FAOI-R5」Lovely 139
P11655题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqclo8p
- 此快照首次捕获于
- 2025/12/04 02:36 3 个月前
- 此快照最后确认于
- 2025/12/04 02:36 3 个月前
题目描述
对于一个 串 (下标从 开始),我们定义它的一个区间 是极长颜色段,当且仅当它同时满足以下条件:
- 若 ,;
- 若 ,;
- 。
定义 为 的不同极长颜色段数。
定义 的值为所有恰好包含 个 和 个 的 串 的 之和。
回答 个问题,每次给出 的值,求 的值。
样例
输入
CPP3
2 2
4 6
7 8
输出
CPP18
1218
54483
算法
(组合计数、逆元)
易得 。
先考虑 ,由于有 个 串 ,所以一共加了 个 。
在 中,对于 ,若 ,对答案的贡献为 。 和 有 和 两种可能,其余的 个数字随便排列,有 中排列。
所以对于 ,所有 的和对答案的贡献为 ,
由于一共有 个 ,所以所有 的和对答案的贡献为 。
综上所述,答案为
预处理 数组存储阶乘, 数组存储逆元, 数组存储阶乘的逆元,可得 。
时间复杂度
C++ 代码
CPP#include <iostream>
using namespace std;
typedef long long LL;
const int N = 2000010, MOD = 1e9 + 7;
int fac[N], inv[N], facinv[N];
LL C(int n, int m) { //计算组合数
return (LL)fac[m] * facinv[m - n] % MOD * facinv[n] % MOD;
}
int main() {
fac[0] = facinv[0] = inv[1] = 1; //初始化
for (int i = 1; i < N; i++) //计算阶乘数组
fac[i] = (LL)fac[i - 1] * i % MOD;
for (int i = 2; i < N; i++) //计算逆元数组
inv[i] = MOD - (LL)inv[MOD % i] * (MOD / i) % MOD;
for (int i = 1; i < N; i++) //计算阶乘的逆元数组
facinv[i] = (LL)facinv[i - 1] * (LL)inv[i] % MOD; //逆元的地推公式
int T;
scanf("%d", &T);
while (T--) {
int n, m;
scanf("%d%d", &n, &m);
int ans = 0;
if (!n || !m) { //特判
puts("1");
continue;
}
//计算答案
ans = (2ll * (n + m - 1) * C(n - 1, m + n - 2) % MOD + C(n, n + m)) % MOD;
printf("%d\n", ans);
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...