【题解】CQOI2015选数

  这题做的时候接连想错了好多次……但是回到正轨上之后依然是一个套路题。(不过这题好像有比莫比乌斯反演更好的做法,莫比乌斯反演貌似是某种能过的暴力ヽ(´ー`)┌)不过能过也就行了吧哈哈。

  首先我们把数字的范围要进行缩小:最大公约数为 \(K\) 那自然所有选出来的数都必须是 \(K\) 的倍数。所以我们改选数为选择是 \(K\) 的多少倍。然后由于是最大公约数,所以选出来的这些数必须最大公约数等于\(1\)。实际上多个数的最大公约数\( = 1\)完全可以和两个数的最大公约数 \( = 1\) 用一样的方法去反演。只不过这题由于数据范围非常的大,所以处理 \(\mu\) 的前缀和必须要使用杜教筛。

#include <bits/stdc++.h>
using namespace std;
#define maxn 1000300
#define db double
#define int long long
int maxx = maxn - 1e2, mod = 1e9 + 7;
int N, K, L, H, ans, Sum[maxn];
int tot, pri[maxn];
map <int, int> Map;
bitset <maxn> is_prime;

int read()
{
    int x = 0, k = 1;
    char c;
    c = getchar();
    while(c < ‘0‘ || c > ‘9‘) { if(c == ‘-‘) k = -1; c = getchar(); }
    while(c >= ‘0‘ && c <= ‘9‘) x = x * 10 + c - ‘0‘, c = getchar();
    return x * k;
}

int qpow(int x, int times)
{
    int base = 1; x %= mod;
    for(; times; times >>= 1, x = (x * x) % mod)
        if(times & 1) base = (base * x) % mod;
    return base;
}

void Get_Mu()
{
    Sum[1] = 1;
    for(int i = 2; i <= maxx; i ++)
    {
        if(!is_prime[i]) pri[++ tot] = i, Sum[i] = -1;
        for(int j = 1; j <= tot; j ++)
        {
            int tem = i * pri[j];
            if(tem > maxx) break;
            is_prime[tem] = 1;
            if(!(i % pri[j])) { Sum[tem] = 0; break; }
            else Sum[tem] = - Sum[i];
        }
    }
    for(int i = 1; i <= maxx; i ++) Sum[i] = (Sum[i] + Sum[i - 1]) % mod;
}

int Mu(int x)
{
    if(x <= maxx) return Sum[x];
    if(Map[x]) return Map[x];
    int ret = 0;
    for(int l = 2, r; l <= x; l = r + 1)
    {
        r = x / (x / l);
        ret = (ret + (r - (l - 1)) * Mu(x / l) % mod) % mod;
    }
    return Map[x] = (1 - ret + mod) % mod;
}

int Solve(int n, int m)
{
    int ret = 0;
    for(int l = 1, r; l <= m; l = r + 1)
    {
        if(n / l) r = min((n / (n / l)), (m / (m / l)));
        else r = (m / (m / l));
        ret += qpow(m / l - n / l, N) % mod * (Mu(r) - Mu(l - 1)) % mod;
        ret %= mod;
    }
    return ret;
}

signed main()
{
    N = read(), K = read(), L = read(), H = read(), ans = 0;
    Get_Mu();
    int l = floor((db) (L - 1) / (db) K), r = floor((db) H / (db) K);
    ans = Solve(l, r);
    printf("%lld\n", (ans + mod) % mod);
    return 0;
}

原文地址:https://www.cnblogs.com/twilight-sx/p/9164026.html

时间: 2024-08-30 04:21:19

【题解】CQOI2015选数的相关文章

BZOJ 3930: [CQOI2015]选数 递推

3930: [CQOI2015]选数 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=3930 Description 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一步研究.然而他很快发现工作量太大了,于是向你寻求帮助

BZOJ 3930: [CQOI2015]选数

3930: [CQOI2015]选数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 1130  Solved: 532[Submit][Status][Discuss] Description 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一步研究.然而他很快发现工作量太大了,于是向你寻求帮助.你的任务很简

【刷题】BZOJ 3930 [CQOI2015]选数

Description 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一步研究.然而他很快发现工作量太大了,于是向你寻求帮助.你的任务很简单,小z会告诉你一个整数K,你需要回答他最大公约数刚好为K的选取方案有多少个.由于方案数较大,你只需要输出其除以1000000007的余数即可. Input 输入一行,包含4个空格分开的正整数,依次为N,K,L和H. O

BZOJ3930:[CQOI2015]选数——题解

http://www.lydsy.com/JudgeOnline/problem.php?id=3930 https://www.luogu.org/problemnew/show/P3172#sub 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一步研究.然而他很快发现工作量太大了,于是向你寻求帮助.你的任务很简单,小z会告诉你一个整数K,你需要回答他最

BZOJ3930 [CQOI2015]选数 【容斥】

题目 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一步研究.然而他很快发现工作量太大了,于是向你寻求帮助.你的任务很简单,小z会告诉你一个整数K,你需要回答他最大公约数刚好为K的选取方案有多少个.由于方案数较大,你只需要输出其除以1000000007的余数即可. 输入格式 输入一行,包含4个空格分开的正整数,依次为N,K,L和H. 输出格式 输出一个整数

CQOI2015 选数

粘题目描述: 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案. 小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一步研究. 然而他很快发现工作量太大了,于是向你寻求帮助. 你的任务很简单,小z会告诉你一个整数K,你需要回答他最大公约数刚好为K的选取方案有多少个.由于方案数较大,你只需要输出其除以1000000007的余数即可. 题解: 容斥+递推.如果我们在区间[l,r]种任取n个不全相同的数时,他们的g

CQOI2015 选数+酱油记

昨天我们考了CQOI2015的题..那还是找一道最可做的写一写好了>.<.. 考试的结果还是不多说了..反正我是知道暴力乱搞高精度的重要性了..骗分的OI才有随机性才好玩,嘛... 成绩不忍直视但竟然还没出前三..感人肺腑... 怎么觉得自从看了CLJ犇的Blog之后越来越喜欢模仿他们的语气卖萌了呢~~ 还是总结一下考试好了,嗯... 感觉我考的时候还是不太在状态..然后有的题目想出来了之后就不太想打了= =..然后四处duang啊duang..时间一下子就过去了呢>.< 根据C老

Luogu P3172 [CQOI2015]选数

这题的反演做法好像很不可食用啊还得套一个杜教筛 我们注意到题目一个重要的性质:\(H-L\le10^5\),看起来可以好好利用一下. 我们首先转化问题,类似于许多和\(\gcd\)有关的问题,我们将原来的最大公约数\(K\)想办法变成\(1\) 这个怎么处理呢,其实很简单,将\(L\)变为\(\lceil \frac{L}{K}\rceil\),将\(R\)变为\(\lfloor\frac{H}{K}\rfloor\). 显然这样我们把问题转化为:在\([L,H]\)种取\(N\)次数使它们的\

bzoj3930 [CQOI2015]选数

Description 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一步研究.然而他很快发现工作量太大了,于是向你寻求帮助.你的任务很简单,小z会告诉你一个整数K,你需要回答他最大公约数刚好为K的选取方案有多少个.由于方案数较大,你只需要输出其除以1000000007的余数即可. Input 输入一行,包含4个空格分开的正整数,依次为N,K,L和H. O