代码改变世界

Co-prime(容斥定理)

2019-08-15 21:10  木木王韦  阅读(332)  评论(0)    收藏  举报

Co-prime

Given a number N, you are asked to count the number of integers between A and B inclusive which are relatively prime to N.
Two integers are said to be co-prime or relatively prime if they have no common positive divisors other than 1 or, equivalently, if their greatest common divisor is 1. The number 1 is relatively prime to every integer.
Input
The first line on input contains T (0 < T <= 100) the number of test cases, each of the next T lines contains three integers A, B, N where (1 <= A <= B <= 10 15) and (1 <=N <= 10 9).
Output
For each test case, print the number of integers between A and B inclusive which are relatively prime to N. Follow the output format below.
Sample Input
2
1 10 2
3 15 5
Sample Output
Case #1: 5
Case #2: 10

Hint
In the first test case, the five integers in range [1,10] which are relatively prime to 2 are {1,3,5,7,9}.

当有n个需要选择时,一共被选择的次数减去被选择两次的个数,加上被选择三次的,减去被选择四次的,依次类推,就是被选择的并集;
ac代码:

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;

long long t,sum1,sum2,cnt,cnt1,a,b,n,m[105],c=0;

int main(){
	cin>>t;
	while(t--){
		memset(m,0,sizeof(m));
		cin>>a>>b>>n;
		cnt=0;
		//cout<<"%%%"<<cnt<<"  "<<n<<endl;
		for(int i=2;i*i<=n;i++){//质因子分解 
			if(n%i==0){//找到n的因子 
				cnt++;
				m[cnt]=i;
			//	cout<<"  "<<i<<" ";
			}
			//cout<<" N:  "<<n<<endl;
			while(n%i==0){
				n/=i;
			} 
			
		}
		//cout<<"ccccnt:"<<cnt<<"n"<<n<<endl;
		if(n!=1){
			cnt++;
			m[cnt]=n;
		//	cout<<"NNN:"<<n<<"   "<<endl;
		}
		//cout<<"ccnntt:"<<cnt<<endl;
		sum1=0;
		int l=1<<cnt;
		//cout<<"CNT:"<<cnt<<"   1<<cnt  :  "<<l<<endl;
		for(int i=1;i<(1<<cnt);i++){//1<<cnt即2的cnt次方,即2进制的位数 
			sum2=1;
			cnt1=0;
			for(int j=0;j<cnt;j++){
				int k=1&(i>>j); 
				//cout<<"i:"<<i<<"   j:"<<j<<"  i>>j:"<<k<<endl; 
				if(1&(i>>j)){//i>>j的意思是将i的二进制向左移j位,按位与1,奇数为1,偶数为0 
					sum2*=m[j+1];
					cnt1++;
					//cout<<"i  j :"<<i<<"   "<<j<<endl; 
				}
			}
			//cout<<"sum2:"<<sum2<<endl;
			if(cnt1&1){
				sum1+=b/sum2;
				sum1-=(a-1)/sum2;
			}
			else{
				sum1-=b/sum2;
				sum1+=(a-1)/sum2;
			}
		}
		cout<<"Case #"<<++c<<": "<<b-a+1-sum1<<endl;
	}
	return 0;
}

/*
2
1 20 12
3 15 5
*/