Description

求有多少单调递增的数列 \(a_1,a_2,...,a_n\),对于任意一个 \(x\) 都满足,对于任意一种排列 \(p\),都有 \(x \mod a_{p_1} \mod a_{p_2} \mod ... \mod a_{p_n} = Const\) 成立。

Solution

首先考虑只有两个数的情况,\(x \mod a \mod b = x \mod b \mod a\) 成立当且仅当 \(a,b\) 中大的是小的的倍数。

猜想序列中任何一个数必须是最小数的倍数。充分性是显然的。

假设有一个数不是最小数的倍数,那么将其他是倍数的数打成一个整体,一些是倍数的数的连续处理本质上等价于对最小的那个数取模,因此转化为上面只有两个数的情况。这样就反证了一个数不是最小数的倍数的情况是不存在的,不止一个数的情况同理。

我们枚举序列中的最小数 \(i\),那么它的倍数有 \([n/i]-1\) 个,我们要从这些中选出 \(k-1\) 个,暴力计算组合数即可。

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 1000005;
const int mod = 998244353;

vector<int> frac(N + 2);

void presolve()
{
    frac[0] = 1;
    for (int i = 1; i <= N; i++)
        frac[i] = frac[i - 1] * i % mod;
}

int qpow(int p, int q)
{
    return (q & 1 ? p : 1) * (q ? qpow(p * p % mod, q / 2) : 1) % mod;
}

int inv(int p)
{
    return qpow(p, mod - 2);
}

int ncr(int n, int m)
{
    if (n < 0 || m < 0 || n < m)
        return 0;
    return frac[n] * inv(frac[m]) % mod * inv(frac[n - m]) % mod;
}

signed main()
{
    int n, k;
    cin >> n >> k;
    int ans = 0;
    presolve();
    for (int i = 1; i <= n; i++)
    {
        ans += ncr(n / i - 1, k - 1);
        ans %= mod;
    }
    cout << ans << endl;
}

相关文章:

  • 2021-08-14
  • 2021-11-15
  • 2022-12-23
  • 2021-05-07
  • 2021-09-14
  • 2021-07-01
  • 2022-01-17
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-06-28
  • 2021-11-02
  • 2021-09-24
  • 2021-07-05
  • 2022-02-08
相关资源
相似解决方案