给定你一个数n,请你统计出在[a,b]这个区间中和n互质的数的个数。
两个数互质当且仅当他们除了1之外没有其他的公共因子或者他们最大的公共因子是1。1和任何数是互素的假设m=12,n=30.
第一步:求出n的质因子:2,3,5;
第二步:(1,m)中是n的因子的倍数当然就不互质了(2,4,6,8,10)->n/2 6个,(3,6,9,12)->n/3 4个,(5,10)->n/5 2个。
如果是粗心的同学就把它们全部加起来就是:6+4+2=12个了,那你就大错特错了,里面明显出现了重复的,我们现在要处理的就是如何去掉那些重复的了!
第三步:这里就需要用到容斥原理了,公式就是:n/2+n/3+n/5-n/(2*3)-n/(2*5)-n/(3*5)+n/(2*3*5).
第四步:我们该如何实现呢?我在网上看到有几种实现方法:dfs(深搜),队列数组,位运算三种方法都可以!上述公式有一个特点:n除以奇数个数相乘的时候是加,n除以偶数个数相乘的时候是减。我这里就写下用队列数组如何实现吧:我们可以把第一个元素设为-1然后具体看代码如何实现吧!
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int N=100005;
vector v;
ll re(ll x){
ll cnt=0;
ll u=1;
ll ans=0;
for(ll i=1;i<(1ll<1;
cnt=0;
for(int j=0;jif((1ll<if(cnt&1ll){
ans+=x/u;
}else{
ans-=x/u;
}
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
ll a,b,n;
bool f=0;
ll cnt=0;
v.clear();
scanf("%lld%lld%lld",&a,&b,&n);
for(ll i=2;i*i<=n;i++){
if(n%i==0){
v.push_back(i);
while(n%i==0){
n/=i;
}
}
}
if(n!=1){
v.push_back(n);
}
//cout<
ll ans=b-re(b)-(a-re(a-1)-1);
cout<