南京理工校赛 C count_prime

上次的广工业刚刚出过容斥的题,然而当初那道题问学长,学长说不会,自己看别人博客,博客里说了下是容斥原理,剩下的只有代码,看到别人写得那么长的代码(其实也不算长,只是没用头文件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));
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值