http://acm.hdu.edu.cn/showproblem.php?pid=4135

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.

 

题目大意:求[a,b]区间与n互素的数的个数

思路:首先转化为前b个数满足的个数减去前a-1个数满足的个数

前num个数中与n互素的数的个数不好算,转化为num-前num个数中与n不互素(即除1外无公因数)的个数

将n分解为若干素数的乘积,求前num个数中有这些素数作为其因数的数的个数,比如前num个数中以3为因数的数有num/3个,

然后容斥定理,奇加偶减,枚举2^k中组合就行了,k为素数因数个数。

实现方式有三种,dfs枚举子集,队列数组,二进制枚举。

我新学了队列数组。

第一次出了小问题:第一次solve()把n给分解了,第二次n就不对了。

#include<bits/stdc++.h>
using namespace std;
#define ll long long

ll t,a,b,n;

ll solve(ll num,ll n)
{
	vector<int> prime,que;
	int m=sqrt(n+0.5);
	for(int i=2;i<=m;i++)if(n%i==0)
	{
		prime.push_back(i);
		while(n%i==0)n/=i;
	}
	if(n>1)prime.push_back(n);
	que.push_back(-1);
	for(int i=0;i<prime.size();i++)
	{
		int k=que.size();
		for(int j=0;j<k;j++)que.push_back(prime[i]*que[j]*-1);
	}
	ll ans=0;
	for(int i=1;i<que.size();i++)ans+=num/que[i];
	return num-ans;
}

int main()
{
//	freopen("input.in","r",stdin);
	int cnt=0;
	cin>>t;
	while(t--)
	{
		cin>>a>>b>>n;
		cout<<"Case #"<<++cnt<<": "<<solve(b,n)-solve(a-1,n)<<endl;
	}
	return 0;
}