求[a, b]区间内与n互质的个数

   #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<bits/stdc++.h>
    using namespace std;
    long long s[1020],k;
    void prime(long long m)//求一个数的素因子
    {
        long long i;
           k=0;
        for(i=2;i*i<=m;i++)
        {
            if(m%i==0)
            {
                s[k++]=i;
                while(m%i==0)
                    m/=i;
    //printf("%d\n",m);
            }
        }
            if(m>1)
                s[k++]=m;

                //printf("###\n");
    }
    long long quc(long long m)//队列数组实现容斥原理
    {
      long long p[10020],i,j,t=0,sum=0,z;
        p[t++]=-1;
        for(i=0;i<k;i++)
        {
            z=t;
            for(j=0;j<z;j++)
            {
                p[t++]=p[j]*s[i]*(-1);
            }
        }
        for(i=1;i<t;i++)
            sum+=m/p[i];
        return sum;
    }
    int main()
    {
        long long n;
        scanf("%lld",&n);
        while(n--)
        {
            long long a,b,m,sum;
            scanf("%lld %lld",&a,&m);
            long long t = __gcd(a, m);
            a = a / t;
            m = m / t;
               prime(m);
            sum=(a + m - 1)-quc(a + m - 1)-(a-1)+quc(a-1);
            printf("%lld\n",sum);
        }
    }

 

当r特别大的时候,时间效率会非常低下,那么我们可以考虑容斥定理。

容斥定理的思想:去求解原问题的逆问题−求区间[1,r]中不与n互素的个数。

思路:首先求得n的所有素因子Pi(i=1...k), 通过二进制枚举所有素因子的组合, 如果选取了奇数个素
因子,应该加上对应的个数,而如果是偶数, 则减去即可。

例如6既能2整除,也能被2∗3整除,所以应该剔除重复计数的部分(使用容斥定理)。

假设当前得到的素数组合是k, 那么⌊rk⌋就是[1,r]中能被k整除的数的个数。

详细见容斥定理

详细代码如下

int solve(int r, int n) {
    vector<int>p;
    p.clear();
    for(int 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); //可能n也是素数
    int sum = 0;
    for(int msk = 1; msk < (1<<p.size()); ++msk) {
        int mult = 1, bits = 0;
        for(int i = 0; i < p.size(); ++i) {
            if(msk & (1<<i)) { //选择了第i个素数因子 
                bits++; 
                mult *= p[i];
            }
        }
        int cur = r / mult;
        if(bits & 1) sum += cur;
        else sum -= cur;
    } 
    return r - sum;
}

 

posted @ 2020-01-31 19:13  jvruodejxt  阅读(268)  评论(0编辑  收藏  举报

Contact with me