JXOI 2018 简要题解

「JXOI2018」游戏

题意

可怜公司有 \(n\) 个办公室,办公室编号是 \(l\sim 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} \times (tot - 1)! \times (n - tot)! \times 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;

}

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

原文地址:https://www.cnblogs.com/zjp-shadow/p/9978542.html

时间: 2024-10-13 22:01:41

JXOI 2018 简要题解的相关文章

JXOI2018简要题解

JXOI2018简要题解 T1 排序问题 题意 九条可怜是一个热爱思考的女孩子. 九条可怜最近正在研究各种排序的性质,她发现了一种很有趣的排序方法: Gobo sort ! Gobo sort 的算法描述大致如下: 假设我们要对一个大小为 \(n\) 的数列 \(a\) 排序. 等概率随机生成一个大小为 \(n\) 的排列 \(p\) . 构造一个大小为 \(n\) 的数列 \(b\) 满足 \(b_i=a_{p_i}\) ,检查 \(b\) 是否有序,如果 \(b\) 已经有序了就结束算法,并

杂题记录及简要题解(三)

以下是大概 5 月初开始做的一些题.以前的简要题解都是骗人的.这次真的是简要题解了(大雾 相对之前改良了一下题目名称的格式. 2017 计蒜之道 初赛 - 腾讯狼人杀 二分答案 \(x\) 后原问题变为检验是否存在选取方案 \((V, E)(|V| = k)\) 使得 \(\sum_\limits{e \in E} w_e - xk \cdot (2n- k)\).式子可以写成 \(\sum_\limits{e \in E} w_e + \frac{k(k - 1)}{2} \cdot 2x -

AGC025简要题解

AGC025简要题解 B RGB Coloring 一道简单题,枚举即可. C Interval Game 考虑可以进行的操作只有两种,即左拉和右拉,连续进行两次相同的操作是没有用的. 左拉时肯定会选择右端点尽量小的,右拉选择左端点尽量大的,所以排序之后贪心即可. D Choosing Points 首先证明对于所有\(d\),假设让两个不能同时选的点之间连一条边,那么结果是一张二分图. \(d\)是奇数可以黑白染色,\(d\)是偶数的时候,显然连边的两点在同一个颜色内.那么我们可以只考虑这个颜

月考简要题解

模拟赛简要题解 一下题目均可在loj上找到 10178. 「一本通 5.5 例 4」旅行问题 简单题,将n扩大到2 * n,单调队列即可,注意正反向. #include<iostream> #include<cstring> #include<cmath> #include<cstdio> #include<algorithm> using namespace std; typedef long long ll; const int N=2000

BJOI2018简要题解

BJOI2018简要题解 D1T1 二进制 题意 pupil 发现对于一个十进制数,无论怎么将其的数字重新排列,均不影响其是不是 \(3\) 的倍数.他想研究对于二进制,是否也有类似的性质. 于是他生成了一个长为 \(n\) 的二进制串,希望你对于这个二进制串的一个子区间,能求出其有多少位置不同的连续子串,满足在重新排列后(可包含前导 \(0\))是一个 \(3\) 的倍数.两个位置不同的子区间指开始位置不同或结束位置不同. 由于他想尝试尽量多的情况,他有时会修改串中的一个位置,并且会进行多次询

【简要题解】Hihocoder 重复旋律1-8简要题解

[简要题解]Hihocoder 重复旋律1-8简要题解 编号 名称标签 难度 1403 后缀数组一·重复旋律 Lv.4 1407 后缀数组二·重复旋律2 Lv.4 1415 后缀数组三·重复旋律3 Lv.4 1419 后缀数组四·重复旋律4 Lv.4 1445 后缀自动机二·重复旋律5 Lv.4 1449 后缀自动机三·重复旋律6 Lv.4 1457 后缀自动机四·重复旋律7 Lv.1 1465 后缀自动机五·重复旋律8 Lv.1 1466 后缀自动机六·重复旋律9 Lv.1 后缀数组 思路简单

《信奥一本通》提高版—简要题解

<信奥一本通>提高版-简要题解 贪心 活动安排: 按右端点排序,因为越早结束越好. 然后从1扫到n,每次比较当前位置线段的左端点是否大于上一个选的线段的右端点.如果大于,那么ans++,将上一个选的线段的右端点更新为当前线段的右端点:如果小于,那什么都不用做.因为选上一条一定比选当前这一条更优(结束时间更早). 种树 按右端点排序,对于每个区间的需求,从右端往左端扫,只要没种到树的就种,ans++. 因为要使前面的需求尽量与后面的需求重叠,从而使树的数量最少 喷水装置 观察+画图发现对于一个圆

【题解】CF616(Div 2)简要题解

[题解]CF616(Div 2)简要题解 A 分类讨论 若数码和是奇数 若最后一个数是奇数:找到从前往后第一个奇数数位删掉 若最后一个数是偶数:不断删除最后一个数直到这个剩下的数是奇数,由于之前删掉的数都是偶数所以对数码和\(\mod 2\)不会有影响.再做一遍第一个算法即可. 若数码和是偶数 若最后一个数是奇数:符合条件 若最后一个数是偶数:不断删除最后一个数直到奇数.由于之前删掉的数都是偶数所以对数码和\(\mod 2\)不会有影响,直接输出即可. 最后要判断一下前导零. B 可以发现若有合

Tsinghua 2018 DSA PA3简要题解

CST2018 3-1-1 Sum (15%) 简单的线段树,单点修改,区间求和. 很简单. CST2018 3-1-2 Max (20%) 高级的线段树. 维护区间最大和,区间和,左边最大和,右边最大和. 单点修改的时候一路吧区间都改了就好了. 求子段最大值也就判断一下左右就好了. 略微复杂. CST2018 3-2 Not Found (20%) 内存有点小,在考虑按层建立trie树? 不太会. CST2018 3-3 Hacker (20%) $18^5$其实并不大,直接预处理hash一下