zoukankan      html  css  js  c++  java
  • luogu3172 [CQOI2015]选数 莫比乌斯反演+杜教筛

    link

    题目大意:有N个数,每个数都在区间[L,H]之间,请求出所有数的gcd恰好为K的方案数

    推式子

    首先可以把[L,H]之间的数字gcd恰好为K转化为[(L-1)/K+1,H/K]之间数字gcd恰好为1

    然后就可以反演了

    下面手误把所有的H都打成了R

    (sum_{i_1=L}^Rsum_{i_2=L}^Rdotssum_{i_N=L}^R[gcd(i_1,i_2,dots,i_N)=1])

    (sum_{i_1=L}^Rsum_{i_2=L}^Rdotssum_{i_N=L}^Rsum_{d|i_1,d|i_2,dots,d|i_N}mu(d))

    (sum_{d=1}^Rmu(d)left(frac{R}d-frac{L-1}d ight)^N)

    显然可以打数论分块

    但是这道题H范围达到10的9次方,果断杜教筛

    注意由于我们的d是枚举到R的(因为右边式子的关系不是相乘,而是相减,所以大于L的项也有效)而>=L的数整除L-1的值为0,所以会导致除法爆炸,所以需要特判,详细请见代码

    #include <cstdio>
    #include <utility>
    #include <map>
    using namespace std;
    
    int p = 1000000007, fuck = 2000000;
    int n, k, l, h;
    bool vis[2000010];
    int prime[2000000], tot, mu[2000010];
    map<int, int> memory;
    
    int qpow(int x, int y)
    {
    	int res = 1;
    	for (x %= p; y > 0; y >>= 1, x = x * (long long)x % p) if (y & 1) res = res * (long long)x % p;
    	return res;
    }
    
    int chumu(int x)
    {
    	if (x <= fuck) return mu[x];
    	if (memory.count(x)) return memory[x];
    	int res = 1;
    	for (int i = 2, j; i <= x; i = j + 1)
    	{
    		j = x / (x / i);
    		res -= (j - i + 1) * chumu(x / i);
    	}
    	return memory[x] = res;
    }
    
    int main()
    {
    	scanf("%d%d%d%d", &n, &k, &l, &h);
    	h /= k, l = (l - 1) / k;
    	mu[1] = 1;
    	for (int i = 2; i <= fuck; i++)
    	{
    		if (vis[i] == false) prime[++tot] = i, mu[i] = -1;
    		for (int j = 1; j <= tot && i * prime[j] <= fuck; j++)
    		{
    			vis[i * prime[j]] = true;
    			if (i % prime[j] == 0) break;
    			mu[i * prime[j]] = -mu[i];
    		}
    		mu[i] += mu[i - 1];
    	}
    	int res = 0;
    	for (int i = 1, j; i <= h; i = j + 1)
    	{
    		j = min(h / (h / i), l / i == 0 ? h : l / (l / i));
    		res += qpow((h / i - l / i), n) * (long long)(chumu(j) - chumu(i - 1)) % p;
    		res %= p;
    		if (res < 0) res += p;
    	}
    	printf("%d
    ", res);
    	return 0;
    }
    
  • 相关阅读:
    [BZOJ 1066] [SCOI2007] 蜥蜴 【最大流】
    [BZOJ 1084] [SCOI2005] 最大子矩阵 【DP】
    [BZOJ 1070] [SCOI2007] 修车 【费用流】
    [BZOJ 1878] [SDOI2009] HH的项链
    [BZOJ 3110] [Zjoi2013] K大数查询 【树套树】
    [HDOJ 1171] Big Event in HDU 【完全背包】
    Shell基本语法---函数
    Shell基本语法---shell数组
    Shell基本语法---while语句
    Shell基本语法---for语句
  • 原文地址:https://www.cnblogs.com/oier/p/10323200.html
Copyright © 2011-2022 走看看