本文章由 WyOJ Shojo 从洛谷专栏拉取,原发布时间为 2021-11-29 12:04:10
题解思路:
$2m$ 个数字
{
1 -- 1
2 -- 2
排序
a : 1 1 , b : 2 2
a = [1 , 1] , b = [2 , 2]
}
对于一种合法的数组而言,每个数组出现的次数构成一个大小n的数组 = $[1 , 2]$
1 2 2 2
1 -- 1
2 -- 3
一个 $ab$ 对唯一对应一个数字出现的次数。
可以把题目转化成 :求 $1-n$ 之间的出现次数。
假设 $n = 4$ ,$m = 5$ :
1 -- ? 举例填 3
2 -- ? 举例填 1
3 -- ? 举例填 2
4 -- ? 举例填 4
1 1 1 2 3 3 ………… $a = []$ , $b = []$
数组 1 1 1 2 3 3 4 4 4 4 。
$a = [1 1 1 2 3]$ $b = [3 4 4 4 4]$
$3 + 1 + 2 + 4$ 必须 $= 2m$。
即对应的数加起来必须是 $2m$。
即求$a + b + c + d = 2m$。
$(a , b , c , d)$ 有多少种。
就变成了组合数学中的划分,模板。
结果:$c[n + 2m - 1][n - 1]$。
当然别忘了取模
(调了半个小时,突然发现 $ans = 0$)
代码:
#include <bits\/stdc++.h>\/\/万能头文件
using namespace std;
#define ll int
#define mod 1000000007
int n , m;
inline ll read() {\/\/快读模板
register ll num = 0 , neg = 1;
register char ch = getchar();
while (ch < '0' && ch > '9'){
if (ch == '-')neg = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9') {
num = (num << 1) + (num << 3) + (ch ^ 48);
ch = getchar();
}
return num * neg;
}
inline void print(int num) {\/\/快输模板
if (num < 0)putchar('-') , num = -num;
if (num > 9)print(num \/ 10);
putchar(num % 10 + '0');
}
long long kuaipow(long long a , long long b , long long m) {\/\/快速幂加取模
long long ans = 1;
while (b > 0) {
if (b & 1)ans = ans * a % m;
a = a * a % m;
b >>= 1;
}
return ans;
}
long long inv(long long a) {
return kuaipow(a , mod - 2 , mod);\/\/调用函数
}
int main() {
n = read() , m = read();\/\/读入
long long ans = 1;\/\/储存最终答案
for (int i = 1; i <= n - 1; ++ i)\/\/计算组合数学
ans = ans * inv(i) % mod;\/\/要取模!!!
for (int i = 1; i <= 2 * m; ++ i)\/\/计算组合数学
ans = ans * inv(i) % mod;
for (int i = 1; i <= n + 2 * m - 1; ++ i)\/\/计算组合数学
ans = ans * i % mod;
print(ans) , putchar('\n');\/\/输出答案
return 0;
}

鲁ICP备2025150228号