上次的广工业刚刚出过容斥的题,然而当初那道题问学长,学长说不会,自己看别人博客,博客里说了下是容斥原理,剩下的只有代码,看到别人写得那么长的代码(其实也不算长,只是没用头文件10+行,看着就头疼,唉~~)自己看时连容斥原理都没搞懂,更别提看代码了,总觉得很难。结果这次比赛又遇到了,懵逼~ 刚好今天没比赛,顺手补补题,把容斥原理搞懂了,刚把广工的容斥搞懂,又把这道题给AC了, 唉~好久没一次AC了,这次一把A,好爽大笑, 这道题只需要将n分解出的质因数存在数组里,然后两遍容斥dfs分别求出总区间与n非质的数,以及前一段区间与n非质的数,接着中间区间的数字个数再减去前面的数,就A了~~~
count_prime
Time Limit: 1000ms
Memory Limit: 65536KB
Description
给定你一个数n,请你统计出在[a,b]这个区间中和n互质的数的个数。两个数互质当且仅当他们除了1之外没有其他的公共因子或者他们最大的公共因子是1。1和任何数是互素的。
Input
第一行输入一个整数T(1 <= T <= 100),表示T组测试数据。接下来T行,每行3个整数a,b,n(1 <= a <=b <=10^15, 1<= n <= 10^9),用空格隔开。
Output
输出一个整数表示和n互质的数的个数。
Sample Input
2
1 10 2
3 10 5
Sample Output
5
6
代码:
#include<stdio.h>
#define ll long long
ll a[40],b[40],s1,s2,k,x,y;
ll gcd(ll aa,ll bb)
{
return bb?gcd(bb,aa%bb):aa;
}
ll lcm(ll aa,ll bb)
{
return aa/gcd(aa,bb)*bb;
}
void dfs(ll qi,ll shu,ll mo)
{
if(qi==k)
{
if(mo)
{
if(mo&1)
s1+=y/shu;
else
s1-=y/shu;
}
return;
}
dfs(qi+1,shu,mo);
shu=lcm(shu,a[qi]);
if(shu<=y)
dfs(qi+1,shu,mo+1);
}
void dfss(ll qi,ll shu,ll mo)
{
if(qi==k)
{
if(mo)
{
if(mo&1)
s2+=(x-1)/shu;
else
s2-=(x-1)/shu;
}
return;
}
dfss(qi+1,shu,mo);
shu=lcm(shu,a[qi]);
if(shu<=x-1)
dfss(qi+1,shu,mo+1);
}
int main()
{
int N;
scanf("%d",&N);
while(N--)
{
ll i,j,n;
scanf("%lld%lld%lld",&x,&y,&n);
k=0,s1=0,s2=0;
for(i=2; i*i<=n; i++)
{
if(n%i==0)
{
while(n%i==0)
n/=i;
a[k++]=i;
}
}
if(n>1)
a[k++]=n;
dfs(0,1,0);
dfss(0,1,0);
printf("%lld\n",y-x+1-(s1-s2));
}
}