[CF1359E] Modular Stability

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;
}
原文地址:https://www.cnblogs.com/mollnn/p/14116937.html