zoukankan      html  css  js  c++  java
  • hdu1695(莫比乌斯反演+容斥)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1695

    题目是求 在区间[a,b]选一个数x,区间[c,d]选一个数y,求满足gcd(x,y) = k 的个数

    题目给出了条件,可以认为所有的样例中,a = b = 1,那么就是在区间[1,b]和区间[1,d]中分别选择两个数求gcd(x,y) = k的个数

    我们让区间[1,b]和[1,d]变为[1,b/k]和[1,d/k],这里就可以转化为求gcd(x,y) = 1的个数

    我们假设  f 是gcd(x,y) = n的个数,F 是gcd(x,y) = n的倍数的个数

    显然 F 和 f  存在如下倍数关系,即:

                                                                 

    设b/k = m,d/k = n,若要求gcd(x,y) =  z 的倍数的个数,那么则F(z) 显然为  (m/z)*(n/z)

    由莫比乌斯反演得:

                                    

    莫比乌斯函数:

    其中莫比乌斯函数的线性筛模板如下:

    ll prime[maxn],mu[maxn],vis[maxn],F[maxn];
    void get_mu() {  //莫比乌斯函数线性筛 
    	int N = maxn;
    	memset(prime,0,sizeof(prime));
    	memset(mu,0,sizeof(mu));
    	memset(vis,0,sizeof(vis));
    	mu[1] = 1;
    	int cnt = 0;
    	for(int i = 2;i<N;i++){
    		if(!vis[i]){
    			prime[cnt++] = i;
    			mu[i] = -1;
    		}
    		for(int j = 0;j<cnt && i*prime[j]<N;j++){
    			vis[i*prime[j]] = 1;
    			if(i%prime[j]) mu[i*prime[j]] = -mu[i];
    			else{
    				mu[i*prime[j]] = 0;
    				break;
    			}
    		}
    	}
    }

    题目转化为在区间[1,b/k]和[1,d/k]中求gcd(x,y) = 1的对数,其实就是求f(1)了,直接计算f (1)。

    因为题目要求如(2,1)和(1,2)是相同的实数对,所以要去重,而重复部分是在f(1)求解过程中的u(1)*F(1) + u(2)*F(2) + u(3)*F(3) + ........+u(min(m,n))*F(min(m,n)),这部分答案除以2是重复累加的,最后再计算一遍减去即可。

    AC代码:

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define maxn 100005
    using namespace std;
    typedef long long ll;
    const int INF = 1 << 30;
    const int MOD = 1e9 + 7;
    ll prime[maxn],mu[maxn],vis[maxn],F[maxn];
    void get_mu() {  //莫比乌斯函数线性筛 
    	int N = maxn;
    	memset(prime,0,sizeof(prime));
    	memset(mu,0,sizeof(mu));
    	memset(vis,0,sizeof(vis));
    	mu[1] = 1;
    	int cnt = 0;
    	for(int i = 2;i<N;i++){
    		if(!vis[i]){
    			prime[cnt++] = i;
    			mu[i] = -1;
    		}
    		for(int j = 0;j<cnt && i*prime[j]<N;j++){
    			vis[i*prime[j]] = 1;
    			if(i%prime[j]) mu[i*prime[j]] = -mu[i];
    			else{
    				mu[i*prime[j]] = 0;
    				break;
    			}
    		}
    	}
    }
    int main(){
    	int t;
    	ios::sync_with_stdio(false);
    	cin>>t;
    	int cnt = 1;
    	get_mu();
    	while(t--){
    	cout<<"Case "<<cnt<<": ";
    	cnt++;
    	int a,b,c,d,k;
    	cin>>a>>b>>c>>d>>k;
    	if (k == 0) {
    		cout<<0<<endl;
    		continue;
    	}
    	b/=k,d/=k;
    	ll ans = 0,t = 0;
    	for(int i= 1;i<=min(b,d);i++){
    		ans+=(long long)mu[i]*(b/i)*(d/i);
    	}
    	for(int i = 1;i<=min(b,d);i++){
    		t+=(long long)mu[i]*(min(b,d)/i)*(min(b,d)/i);//计算重复部分 
    	}
    	cout<<ans-t/2<<endl;
    	}
    }
  • 相关阅读:
    标题党的进步:道字大旗不再扯,美为号召又开张
    dwr自动生成的js文件到底在哪里?
    JavaScript全局优化带来的负面效果……
    内训资料公开:设计师的实战过程(1)
    元语言基础技术之:在JS中如何自由地创建函数
    QoBean的元语言系统(一)
    Oracle面向服务的架构
    对JavaScript的eval()中使用函数的进一步讨论~
    KEGG and Gene Ontology Mapping in Bioinformatic Method
    mysql user administration
  • 原文地址:https://www.cnblogs.com/AaronChang/p/12129624.html
Copyright © 2011-2022 走看看