zoukankan      html  css  js  c++  java
  • 求[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
    ",m);
                }
            }
                if(m>1)
                    s[k++]=m;
    
                    //printf("###
    ");
        }
        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
    ",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;
    }
  • 相关阅读:
    一文搞懂字符集
    机器视觉之eVision
    PID调节
    激光切割质量主要影响因素
    155. 最小栈
    111.二叉树最小深度
    110. 平衡二叉树
    108.将有序数组转换为二叉搜索树
    107. 二叉树的层次遍历 II
    104. 二叉树的最大深度
  • 原文地址:https://www.cnblogs.com/jrjxt/p/12246328.html
Copyright © 2011-2022 走看看