E - Modular Stability[组合数][思维]
Time Limit Per Test | Memory Limit Per Test | input | output |
---|---|---|---|
2 seconds | 512 megabytes | standard input | standard output |
题意
给定 n , k n, k n,k,从 1 − n 1 - n 1−n 中取 k k k 个不同的数组成一个数组
若该数组满足:任意调换数组值的位置
x m o d a 1 m o d a 2 m o d . . . m o d a k x \mod a_1 \mod a_2 \mod ... \mod a_k xmoda1moda2mod...modak 对于任意 x x x 得到的值都相同
则为所要求的数组
问这样的数组总共有多少个
做法
要满足上述条件,必须要 k k k 个数的最小公因数是相同的
假设可以整除 y y y 的数共有 c n t cnt cnt 个
当 c n t > = k cnt >= k cnt>=k,只要从 c n t − 1 cnt - 1 cnt−1 个中任意选 k − 1 k - 1 k−1 个
c n t − 1 cnt - 1 cnt−1 是因为 y y y 自己也算进去了, k − 1 k - 1 k−1 是除了 y y y 以外要选的个数
也就是组合数相加
样例1
输入
7 3
输出
16
样例2
输入
3 7
输出
0
样例3
输入
1337 42
输出
95147305
样例4
输入
500000 1
输出
1
代码
#include <bits/stdc++.h>
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const ll INF = 1e18;
const int mod = 998244353;
const int inf = 0x3f3f3f3f;
const int maxn = 5e5 + 5;
ll fac[maxn];
ll inv[maxn];
ll fpow(ll a, ll b) {
ll ans = 1;
while(b) {
if(b & 1) ans = ans * a % mod;
a = a * a % mod;
b >>= 1;
}
return ans;
}
void handle(int n) {
fac[0] = 1;
for(int i = 1; i <= n; ++i)
fac[i] = fac[i - 1] * i % mod;
inv[n] = fpow(fac[n], mod - 2);
for(int i = n - 1; i >= 0; --i)
inv[i] = inv[i + 1] * (i + 1) % mod;
}
ll C(int n, int m) {
if(n < 0 || m < 0 || n < m) return 0;
return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
int main() {
int n, k;
scanf("%d%d", &n, &k);
if(n < k) puts("0");
else{
handle(n);
ll ans = 0;
for(int i = 1; i * k <= n; ++i) // 保证能取到 k 个 i 的倍数
ans = (ans + C(n / i - 1, k - 1)) % mod;
printf("%lld\n", ans);
}
return 0;
}