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

    题目描述

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

    输入

    输入一行,包含4个空格分开的正整数,依次为N,K,L和H。

    输出

    输出一个整数,为所求方案数。

    样例输入

    2 2 2 4

    样例输出

    3


    题解

    莫比乌斯反演+杜教筛

    其中xi表示第i个数的取值。

    然后这里就可以分块来求。

    由于h的范围过大,所以需要使用杜教筛求mu的前缀和,详见 bzoj3944

    #include <cstdio>
    #include <map>
    #define N 1000010
    #define mod 1000000007
    using namespace std;
    typedef long long ll;
    const int m = 1000000;
    map<int , int> f;
    map<int , int>::iterator it;
    int mu[N] , sum[N] , prime[N] , tot;
    bool np[N];
    ll pow(ll x , int y)
    {
    	ll ans = 1;
    	while(y)
    	{
    		if(y & 1) ans = ans * x % mod;
    		x = x * x % mod , y >>= 1;
    	}
    	return ans;
    }
    int query(int n)
    {
    	if(n <= m) return sum[n];
    	it = f.find(n);
    	if(it != f.end()) return it->second;
    	int i , last , ans = 1;
    	for(i = 2 ; i <= n ; i = last + 1) last = n / (n / i) , ans -= (last - i + 1) * query(n / i);
    	return f[n] = ans;
    }
    int main()
    {
    	int i , j , p , k , l , r , last;
    	ll ans = 0;
    	mu[1] = sum[1] = 1;
    	for(i = 2 ; i <= m ; i ++ )
    	{
    		if(!np[i]) mu[i] = -1 , prime[++tot] = i;
    		for(j = 1 ; j <= tot && i * prime[j] <= m ; j ++ )
    		{
    			np[i * prime[j]] = 1;
    			if(i % prime[j] == 0)
    			{
    				mu[i * prime[j]] = 0;
    				break;
    			}
    			else mu[i * prime[j]] = -mu[i];
    		}
    		sum[i] = sum[i - 1] + mu[i];
    	}
    	scanf("%d%d%d%d" , &p , &k , &l , &r) , r /= k , l = (l - 1) / k;
    	for(i = 1 ; i <= r ; i = last + 1)
    	{
    		last = r / (r / i);
    		if(l >= i) last = min(last , l / (l / i));
    		ans = (ans + (query(last) - query(i - 1) + mod) % mod * pow((ll)r / i - l / i , p) % mod) % mod;
    	}
    	printf("%lld
    " , ans);
    	return 0;
    }
    
  • 相关阅读:
    关于lockkeyword
    关于多层for循环迭代的效率优化问题
    Android 面试精华题目总结
    Linux基础回想(1)——Linux系统概述
    linux源代码编译安装OpenCV
    校赛热身 Problem C. Sometimes Naive (状压dp)
    校赛热身 Problem C. Sometimes Naive (状压dp)
    校赛热身 Problem B. Matrix Fast Power
    校赛热身 Problem B. Matrix Fast Power
    集合的划分(递推)
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/7000302.html
Copyright © 2011-2022 走看看