JXOI 2018 简要题解

Posted zjp-shadow

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JXOI 2018 简要题解相关的知识,希望对你有一定的参考价值。

「JXOI2018」游戏

题意

可怜公司有 (n) 个办公室,办公室编号是 (lsim l+n-1) ,可怜会事先制定一个顺序,按照这个顺序依次检查办公室。一开始的时候,所有办公室的员工都在偷懒,当她检查完编号是 (i) 的办公室时候,这个办公室的员工会认真工作,并且这个办公室的员工通知所有办公室编号是 (i) 的倍数的办公室,通知他们老板来了,让他们认真工作。因此,可怜检查完第 (i) 个办公室的时候,所有编号是 (i) 的倍数(包括 (i) )的办公室的员工会认真工作。

她发现,对于每种不同的顺序 (p) ,都存在一个最小的 (t(p)) ,使得可怜按照这个顺序检查完前 (t(p)) 个办公室之后,所有的办公室都会开始认真工作。她把这个 (t(p)) 定义为 (p) 的检查时间。

可怜想知道所有 (t(p)) 的和对 (10^9+7) 取模后的结果。

(l, n le 10^7)

题解

比较舒服的签到题。

我们定义 ([l, r]) 中的神仙数 (p) ,当且仅当 (p) 除了 (p) 外的任意一个因子都不存在于 ([l, r]) 中。

这个显然我们可以用线性筛预处理,做到 (O(n)) 的复杂度。其实也可以通过埃筛做到 (O(n ln ln n)) 的复杂度。

假设 ([l, r]) 中的神仙数共有 (tot) 个,那么就意味着只要这 (tot) 个数全部遍历过就可以结束了,反之不能结束。

这是很好证明的,因为这些数不遍历的话,那么不存在别的数能把他们消掉。反之这些数遍历了,别的数都能通过这些数消掉。

那么枚举在第几个数便利完,那么贡献就很好计算了:
[ sum_{i= tot}^{n} {i - 1 choose tot - 1} imes (tot - 1)! imes (n - tot)! imes i ]
假设在 (i) 处结束,那么第 (i) 个必为神仙数,那么就是在前 (i - 1) 个位置填 (tot - 1) 的排列,然后其他数可以随意安排,注意不要漏乘此处的贡献是 (i)

然后线性预处理逆元就可以把复杂度做到 (O(n)) 了。

代码

#include <bits/stdc++.h>

#define For(i, l, r) for(register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for(register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << (x) << endl
#define DEBUG(...) fprintf(stderr, __VA_ARGS__)

using namespace std;


inline bool chkmin(int &a, int b) {return b < a ? a = b, 1 : 0;}
inline bool chkmax(int &a, int b) {return b > a ? a = b, 1 : 0;}

inline int read() {
    int x = 0, fh = 1; char ch = getchar();
    for (; !isdigit(ch); ch = getchar() ) if (ch == '-') fh = -1;
    for (; isdigit(ch); ch = getchar() ) x = (x << 1) + (x << 3) + (ch ^ 48);
    return x * fh;
}

void File() {
#ifdef zjp_shadow
    freopen ("2544.in", "r", stdin);
    freopen ("2544.out", "w", stdout);
#endif
}

typedef long long ll;

const int N = 1e7 + 1e3, Mod = 1e9 + 7;

ll fpm(ll x, int power) {
    ll res = 1;
    for (; power; power >>= 1, (x *= x) %= Mod)
        if (power & 1) (res *= x) %= Mod;
    return res;
}

int l, r, n; ll fac[N], ifac[N];

inline int C(int n, int m) {
    if (n < 0 || m < 0 || m > n) return 0;
    return 1ll * fac[n] * ifac[m] % Mod * ifac[n - m] % Mod;
}

void Init(int maxn) {
    fac[0] = ifac[0] = 1;
    For (i, 1, maxn) fac[i] = 1ll * fac[i - 1] * i % Mod;
    ifac[maxn] = fpm(fac[maxn], Mod - 2);
    Fordown (i, maxn - 1, 1)
        ifac[i] = 1ll * ifac[i + 1] * (i + 1) % Mod;
}

bitset<N> vis;

int main () {
    
    File();

    l = read(); r = read(); n = r - l + 1;
    Init(1e7);

    int tot = 0, ans = 0;
    For (i, l, r) if (!vis[i]) {
        ++ tot; for (int j = i; j <= r; j += i) vis[j] = true;
    }

    For (i, tot, n)
        (ans += 1ll * C(i - 1, tot - 1) * fac[tot] % Mod * fac[n - tot] % Mod * i % Mod) %= Mod;

    cout << ans << endl;

    return 0;

}

后面两题先咕着,似乎不好做。。。

以上是关于JXOI 2018 简要题解的主要内容,如果未能解决你的问题,请参考以下文章

JXOI2018简要题解

JXOI2017 题解

题解 [JXOI2012]奇怪的道路

HAOI2018 简要题解

BJOI2018简要题解

HAOI2018 简要题解