1 介绍
本博客用来记录组合计数相关题目。
2 训练
题目1:1307牡牛和牝牛
C++代码如下,
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010, mod = 5000011;
int n, k;
int f[N], s[N];
int main() {
cin >> n >> k;
f[0] = s[0] = 1;
for (int i = 1; i <= n; ++i) {
f[i] = s[max(i - k - 1, 0)];
s[i] = (s[i-1] + f[i]) % mod;
}
cout << s[n] << endl;
return 0;
}
题目2:1308方程的解
C++代码如下,
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 150;
int k, x;
int f[1000][100][N];
int qmi(int a, int b, int p) {
int res = 1;
while (b) {
if (b & 1) res = res * a % p;
a = a * a % p;
b >>= 1;
}
return res;
}
void add(int c[], int a[], int b[]) {
for (int i = 0, t = 0; i < N; ++i) {
t += a[i] + b[i];
c[i] = t % 10;
t /= 10;
}
}
int main() {
cin >> k >> x;
int n = qmi(x % 1000, x, 1000);
for (int i = 0; i < n; ++i) {
for (int j = 0; j <= i && j < k; j++) {
if (!j) f[i][j][0] = 1;
else add(f[i][j], f[i-1][j], f[i-1][j-1]);
}
}
int *g = f[n-1][k-1];
int i = N - 1;
while (!g[i]) i--;
while (i >= 0) cout << g[i--];
return 0;
}
题目3:1309车的放置
C++代码如下,
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 2010, mod = 100003;
int fact[N], infact[N];
int qmi(int a, int k) {
int res = 1;
while (k) {
if (k & 1) res = (LL)res * a % mod;
a = (LL)a * a % mod;
k >>= 1;
}
return res;
}
int C(int a, int b) {
if (a < b) return 0;
return (LL)fact[a] * infact[a-b] % mod * infact[b] % mod;
}
int P(int a, int b) {
if (a < b) return 0;
return (LL)fact[a] * infact[a-b] % mod;
}
int main() {
fact[0] = infact[0] = 1;
for (int i = 1; i < N; ++i) {
fact[i] = (LL)fact[i-1] * i % mod;
infact[i] = (LL)infact[i-1] * qmi(i, mod - 2) % mod;
}
int a, b, c, d, k;
cin >> a >> b >> c >> d >> k;
int res = 0;
for (int i = 0; i <= k; ++i) {
res = (res + (LL)C(b, i) * P(a, i) % mod * C(d, k - i) % mod * P(a + c - i, k - i)) % mod;
}
cout << res << endl;
return 0;
}
题目4:1310数三角形
C++代码如下,
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
int gcd(int a, int b) {
return b ? gcd(b, a % b) : a;
}
LL C(int n) {
return (LL)n * (n - 1) * (n - 2) / 6;
}
int main() {
int n, m;
cin >> n >> m;
n++, m++;
LL res = C(n*m) - (LL)n * C(m) - (LL)m * C(n);
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= m; ++j) {
res -= 2ll * (gcd(i, j) - 1) * (n - i) * (m - j);
}
}
cout << res << endl;
return 0;
}
题目5:1312序列统计
C++代码如下,
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int p = 1e6 + 3;
int qmi(int a, int k) {
int res = 1;
while (k) {
if (k & 1) res = (LL)res * a % p;
a = (LL)a * a % p;
k >>= 1;
}
return res;
}
int C(int a, int b) {
if (a < b) return 0;
int down = 1, up = 1;
for (int i = a, j = 1; j <= b; i--, j++) {
up = (LL)up * i % p;
down = (LL)down * j % p;
}
return (LL)up * qmi(down, p - 2) % p;
}
int Lucas(int a, int b) {
if (a < p && b < p) return C(a, b);
return (LL)Lucas(a / p, b / p) * C(a % p, b % p) % p;
}
int main() {
int T;
cin >> T;
while (T--) {
int n, l, r;
cin >> n >> l >> r;
cout << (Lucas(r - l + n + 1, r - l + 1) + p - 1) % p << endl;
}
return 0;
}
题目6:1315网格
C++代码如下,
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int N = 100010;
int primes[N], cnt;
bool st[N];
int a[N], b[N];
void init(int n) {
for (int i = 2; i <= n; ++i) {
if (!st[i]) primes[cnt++] = i;
for (int j = 0; primes[j] * i <= n; j++) {
st[primes[j] * i] = true;
if (i % primes[j] == 0) break;
}
}
}
int get(int n, int p) {
int s = 0;
while (n) s += n / p, n /= p;
return s;
}
void mul(int r[], int &len, int x) {
int t = 0;
for (int i = 0; i < len; ++i) {
t += r[i] * x;
r[i] = t % 10;
t /= 10;
}
while (t) {
r[len++] = t % 10;
t /= 10;
}
}
void sub(int a[], int al, int b[], int bl) {
for (int i = 0, t = 0; i < al; ++i) {
a[i] -= t + b[i];
if (a[i] < 0) a[i] += 10, t = 1;
else t = 0;
}
}
int C(int x, int y, int r[N]) {
int len = 1;
r[0] = 1;
for (int i = 0; i < cnt; ++i) {
int p = primes[i];
int s = get(x, p) - get(y, p) - get(x - y, p);
while (s--) mul(r, len, p);
}
return len;
}
int main() {
init(N - 1);
int n, m;
cin >> n >> m;
int al = C(n+m, m, a);
int bl = C(n+m, n+1, b);
sub(a, al, b, bl);
int k = al - 1;
while (!a[k] && k > 0) k --;
while (k >= 0) printf("%d", a[k--]);
return 0;
}
题目7:1316有趣的数列
C++代码如下,
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
const int N = 2000010;
int n, p;
int primes[N], cnt;
bool st[N];
void init(int n) {
for (int i = 2; i <= n; ++i) {
if (!st[i]) primes[cnt++] = i;
for (int j = 0; primes[j] * i <= n; ++j) {
st[i*primes[j]] = true;
if (i % primes[j] == 0) break;
}
}
}
int qmi(int a, int k) {
int res = 1;
while (k) {
if (k & 1) res = (LL)res * a % p;
a = (LL)a * a % p;
k >>= 1;
}
return res;
}
int get(int n, int p) {
int s = 0;
while (n) {
s += n / p;
n /= p;
}
return s;
}
int C(int a, int b) {
int res = 1;
for (int i = 0; i < cnt; ++i) {
int prime = primes[i];
int s = get(a, prime) - get(b, prime) - get(a - b, prime);
res = (LL)res * qmi(prime, s) % p;
}
return res;
}
int main() {
scanf("%d%d", &n, &p);
init(n * 2);
cout << (C(n * 2, n) - C(n * 2, n - 1) + p) % p << endl;
return 0;
}