• [luoguP3172] [CQOI2015]选数(递推+容斥原理)


    传送门

    不会莫比乌斯反演,不会递推。

    但是我会看题解。

    先将区间[L,H]变成(L-1,H],这样方便处理

    然后求这个区间内gcd为k的方案数

    就是求区间((L-1)/k,H/k]中gcd为1的方案数

    有个重要的性质:如果有一些不相同的数,最大的为a,最小的为b,任意选取其中的一些数,则他们的gcd<=a-b

    设f[i]表示gcd为i且所选的数不相同的方案数,但是不好求,只容易求出gcd为i的倍数g[i]的方案数

    考虑容斥原理,f[i] = g[i] - f[2i] - f[3i] - ……

    计算g[i]的时候要把相同的数的方案数减去,因为我们有个前提,只有数都不相同时gcd的大小才能保证

    倒着递推便可以省略g数组

    #include <cstdio>
    #define N 100001
    #define p 1000000007
    #define LL long long
    
    using namespace std;
    
    LL f[N];
    int n, k, l, r, flag, len;
    
    inline LL ksm(LL x, int y)
    {
    	LL ret = 1;
    	for(; y; y >>= 1)
    	{
    		if(y & 1) ret = ret * x % p;
    		x = x * x % p;
    	}
    	return ret;
    }
    
    int main()
    {
    	int i, j, x, y;
    	scanf("%d %d %d %d", &n, &k, &l, &r);
    	if(l <= k && k <= r) flag = 1;
    	l--, l /= k, r /= k, len = r - l;
    	//转变成求区间(l, r]中gcd为1的方案数
    	for(i = len; i >= 1; i--)
    	{
    		x = l / i, y = r / i;
    		f[i] = (LL)(ksm(y - x, n) - (y - x)) % p;
    		for(j = i + i; j <= len; j += i) f[i] = (f[i] - f[j]) % p;
    	}
    	printf("%lld
    ", (f[1] + flag + p) % p);
    	return 0;
    }
    

      

  • 相关阅读:
    Java生产者与消费者(下)
    Java生产者与消费者(上)
    Java中的继承和接口
    syslog(),closelog()与openlog()--日志操作函数
    Nagle算法
    TCP_NODELAY详解
    Linux "零拷贝" sendfile函数中文说明及实际操作分析
    pdflush的工作原理
    proc/sys/net/ipv4/下各项的意义
    求最低价格
  • 原文地址:https://www.cnblogs.com/zhenghaotian/p/8213419.html
Copyright © 2020-2023  润新知