组合数学
逆元
若
递推求乘法逆元
令
代码
void C() {
inv[1] = 1;
for(int i = 2; i < MAXV; ++i) {
inv[i] = 1ll * (p - p / i) * inv[p % i] % p;
}
}
C();
平方求组合数
可以发现,
- 选最后一个:
。 - 不选最后一个:
。
所以
代码
void C() {
for(int i = 0; i < MAXV; ++i) {
c[i][0] = 1;
for(int j = 1; j <= i; ++j) {
c[i][j] = (c[i - 1][j - 1] + c[i - 1][j]) % MOD;
}
}
}
预处理求组合数
众所周知,
令
void C() {
inv[1] = f[0] = Inv[0] = 1;
for(int i = 1; i < MAXV; ++i) {
f[i] = 1ll * f[i - 1] * i % p;
inv[i] = (i > 1 ? 1ll * (p - p / i) * inv[p % i] % p : 1);
Inv[i] = 1ll * Inv[i - 1] * inv[i] % p;
}
}
C();
题目
CSES P1715
题目描述
给定一个字符串
思路
首先在不考虑字符相同的情况下答案明显就是
时空复杂度均为
细节
无。
代码
#include<bits/stdc++.h>
using namespace std;
const int MAXV = 1000001, MOD = 1000000007;
int f[MAXV], nv[MAXV], inv[MAXV], cnt[26], ans;
string s;
void C() {
f[0] = f[1] = nv[1] = inv[0] = inv[1] = 1;
for(int i = 2; i < MAXV; ++i) {
f[i] = 1ll * f[i - 1] * i % MOD;
nv[i] = 1ll * (MOD - MOD / i) * nv[MOD % i] % MOD;
}
for(int i = 2; i < MAXV; ++i) {
inv[i] = 1ll * inv[i - 1] * nv[i] % MOD;
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
C();
cin >> s;
for(int i = 0; i < int(s.size()); ++i) {
cnt[s[i] - 'a']++;
}
ans = f[s.size()];
for(int i = 0; i < 26; ++i) {
ans = 1ll * ans * inv[cnt[i]] % MOD;
}
cout << ans;
return 0;
}
CSES P1716
题目描述
有
思路
可以看做是
时空复杂度均为
细节
无
代码
#include<bits/stdc++.h>
using namespace std;
const int MAXV = 2000001, MOD = 1000000007;
int n, m, f[MAXV], nv[MAXV], inv[MAXV], cnt[26], ans;
void C() {
f[0] = f[1] = nv[1] = inv[0] = inv[1] = 1;
for(int i = 2; i < MAXV; ++i) {
f[i] = 1ll * f[i - 1] * i % MOD;
nv[i] = 1ll * (MOD - MOD / i) * nv[MOD % i] % MOD;
}
for(int i = 2; i < MAXV; ++i) {
inv[i] = 1ll * inv[i - 1] * nv[i] % MOD;
}
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
C();
cin >> n >> m;
cout << ((1ll * f[m + n - 1] * inv[n - 1]) % MOD * inv[m]) % MOD;
return 0;
}
GYM 104386 C
题目描述
有一个数组
思路
令第
时空复杂度均为
细节
注意第一维是
代码
#include<bits/stdc++.h>
using namespace std;
const int MAXV = 2000001, MOD = 1000000007;
int t, n, k, f[MAXV], nv[MAXV], inv[MAXV];
void C() {
f[0] = f[1] = nv[1] = inv[0] = inv[1] = 1;
for(int i = 2; i < MAXV; ++i) {
f[i] = 1ll * f[i - 1] * i % MOD;
nv[i] = 1ll * (MOD - MOD / i) * nv[MOD % i] % MOD;
}
for(int i = 2; i < MAXV; ++i) {
inv[i] = 1ll * inv[i - 1] * nv[i] % MOD;
}
}
void Solve() {
cin >> n >> k;
int x = n + k - 1, y = n - 1;
cout << ((1ll * f[x] * inv[y]) % MOD * inv[x - y]) % MOD << "\n";
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
C();
cin >> t;
while(t--) {
Solve();
}
return 0;
}
CSES P1717
题目描述
有
思路
由于每个小朋友都要收到礼物,所以这就是求错排数,使用 DP。
令
,则方案数为 ,因为 和 已经不会对答案造成影响。 ,则方案数为 ,因为 已经没有作用,可以把 看做 。
所以
细节
代码
#include<bits/stdc++.h>
using namespace std;
const int MAXV = 2000001, MOD = 1000000007;
int n, f[MAXV], nv[MAXV], inv[MAXV], dp[MAXV];
void F() {
f[0] = f[1] = nv[1] = inv[0] = inv[1] = 1;
for(int i = 2; i < MAXV; ++i) {
f[i] = 1ll * f[i - 1] * i % MOD;
nv[i] = 1ll * (MOD - MOD / i) * nv[MOD % i] % MOD;
}
for(int i = 2; i < MAXV; ++i) {
inv[i] = 1ll * inv[i - 1] * nv[i] % MOD;
}
}
int C(int x, int y) {
return ((1ll * f[x] * inv[y]) % MOD * inv[x - y]) % MOD;
}
int A(int x, int y) {
return (1ll * f[x] * inv[y]) % MOD;
}
int Pow(int a, int b) {
int res = 1;
while(b) {
if(b & 1) {
res = (1ll * res * a) % MOD;
}
a = (1ll * a * a) % MOD;
b >>= 1;
}
return res;
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
F();
cin >> n;
dp[0] = 1, dp[1] = 0;
for(int i = 2; i <= n; ++i) {
dp[i] = 1ll * (i - 1) * (dp[i - 1] + dp[i - 2]) % MOD;
}
cout << dp[n];
return 0;
}
Luogu P4071
题目描述
求有多少种
思路
由于有
时空复杂度均为
细节
无。
代码
#include<bits/stdc++.h>
using namespace std;
const int MAXV = 2000001, MOD = 1000000007;
int t, n, m, f[MAXV], nv[MAXV], inv[MAXV], dp[MAXV];
void F() {
f[0] = f[1] = nv[1] = inv[0] = inv[1] = 1;
for(int i = 2; i < MAXV; ++i) {
f[i] = 1ll * f[i - 1] * i % MOD;
nv[i] = 1ll * (MOD - MOD / i) * nv[MOD % i] % MOD;
}
for(int i = 2; i < MAXV; ++i) {
inv[i] = 1ll * inv[i - 1] * nv[i] % MOD;
}
dp[0] = 1, dp[1] = 0;
for(int i = 2; i <= MAXV; ++i) {
dp[i] = 1ll * (i - 1) * (dp[i - 1] + dp[i - 2]) % MOD;
}
}
int C(int x, int y) {
return ((1ll * f[x] * inv[y]) % MOD * inv[x - y]) % MOD;
}
int A(int x, int y) {
return (1ll * f[x] * inv[y]) % MOD;
}
int Pow(int a, int b) {
int res = 1;
while(b) {
if(b & 1) {
res = (1ll * res * a) % MOD;
}
a = (1ll * a * a) % MOD;
b >>= 1;
}
return res;
}
int main() {
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
F();
cin >> t;
while(t--) {
cin >> n >> m;
cout << 1ll * dp[n - m] * C(n, n - m) % MOD << "\n";
}
return 0;
}
本文作者:yaosicheng124
本文链接:https://www.cnblogs.com/yaosicheng124/p/18129812
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步