hdu 4135 Co-prime
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 6051 Accepted Submission(s): 2411
Problem Description
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 <= 1015) and (1 <=N <= 109).
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}.
Source
The Third Lebanese Collegiate Programming Contest
Recommend
lcy | We have carefully selected several similar problems for you: 1796 1434 3460 1502 4136
题解
给出区间【A,B】和数字n 求解 与n互质的数的个数(即与n没有公约数的数的个数),1 <= A <= B <= 10^15 显然不能用暴力求解,所以用到容斥
下面我们一步一步来进行分析:
1 求【A,B】区间与k互质的个数转化成求解【1,B】区间中与n互斥的个数减去【1,A-1】中与k互斥的个数 (A-1 是因为要把A算进去)
2. 接下来问题转化成为求1到一个数n区间内的与k互质的数的个数,那么思路再转换,求互质,可以先求不互质,然后一减不就得到了么?
3. 那么如何求不互质的呢,可以先将k 进行素因子分解,用然后再区间【1,n】 中 ,用 n/素因子 可以得到对应这个素因子的区间内的不互质的个数,然后每个都求一遍,但会有重复的。
下面举个例子:
【1,10】 求关于12的
12 的素因子有 2,3
【1,10】 10/2=5 有5个(2,4,6,8,10)
【1,10】 10 /3=3 有3个(3,6,9)
但是会发现 6重复了
【1,10】 10/(2*3)=1 个-最后结果是 5+3-1=7 个 然后互质的有10 -7=3 个
4. 所以这里有个规律(奇加偶减) 10/2+10/3-10/(2*3)
至于如何求算 有的dfs 和 位运算求解两种把吧
1. 位运算:
用二进制1,0 来表示第几个素因子是否会被用到 如果你求的素因子个数为3 则 i=3时二进制位011 表示第 2 3 个因子被用到
i=1 001 表示只有第3个数被用到
AC1:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll Sovle(ll n,ll r)
{
vector<ll> p; // 存放素因子
for(ll i=2;i*i<=n;i++)
{
if(n%i==0)
{
p.push_back(i); // 若能整除加入
while(n%i==0) n/=i; //循环除尽
}
}
if(n>1) p.push_back(n);
ll ans=0;
for(ll temp =1;temp<(1<<p.size());temp++) //1左移素因子个数位
{
ll multi=1,bits=0; // utli 存放要求的约数 bits是用到的素因子的个数
for(ll i=0;i<p.size();i++) //循环判断每一位是否用到
{
if(temp&(1<<i)) //用到
{
++bits; //用到的个数+1
multi*=p[i]; // 乘到约数中
}
}
ll cur=r/multi; // 求解个数
if(bits&1) ans+=cur; // 奇加偶解
else ans-=cur;
}
return r-ans;
}
int main()
{
int T,n,cases=0;
ll A,B;
cin>>T;
while(T--)
{
cin>>A>>B>>n;
ll res,ans;
ans=Sovle(n,A-1);
res=Sovle(n,B);
printf("Case #%d: %lld\n",++cases,res-ans);
}
return 0;
}
下面是bfs:
AC2:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<ll> fac;
void GetFactor(int n)
{
fac.clear();
for(ll i=2;i*i<=n;i++)
{
if(n%i==0)
{
fac.push_back(i);
while(n%i==0) n/=i;
}
}
if(n>1) fac.push_back(n);
}
ll ans;
void dfs(int cur,int num,ll mul, ll A)
{
if(cur==fac.size())
{
if(num&1) ans-=A/mul;
else ans+=A/mul;
return;
}
dfs(cur+1,num,mul,A);
dfs(cur+1,num+1,mul*fac[cur],A);
}
int main()
{
int T,n,cases=0;
ll A,B;
cin>>T;
while(T--)
{
cin>>A>>B>>n;
GetFactor(n);
ans=0;
dfs(0,0,1,B);
ll res=ans;
ans=0;
dfs(0,0,1,A-1);
printf("Case #%d: %lld\n",++cases,res-ans);
}
return 0;
}