HDU 4135 Co-prime 容斥原理

Posted legend_PawN

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 4135 Co-prime 容斥原理相关的知识,希望对你有一定的参考价值。

题目链接
统计在大区间[A,B]中与N互质的数的个数,其中A,B都在10的15次方级。

暴力肯定不行,正难则反,思考求[A,B]中不与N互质的数的个数,那么该数必然是N的其中一个因子的倍数,所以首先对N的所有因子进行打表,然后根据每一个因子求在[A,B]区间中其倍数的个数。
在不同的因子进行计数的时候可能产生重复,所以进行容斥。
最后,小技巧将区间转化成[1,B]-[1,A-1]求更加方便。
两种容斥的形式:
vis[i]-num[i]通用型:
AC代码:

#include <bits/stdc++.h>
typedef  long long ll;
const int N=1e5;
using namespace std;
ll a,b,n;
int p[N];
int num[N],vis[N];
int main()
    int T,cnt=0;
    scanf("%d",&T);
    while(T--)
        memset(num,0,sizeof(num));
        memset(vis,0,sizeof(vis));
        scanf("%lld%lld%lld",&a,&b,&n);
        int count=0;
        for(int i=1;i*i<=n;i++)
            if(n%i==0)
                p[count++]=i;
                if(i*i!=n)
                    p[count++]=n/i;
            
        
        sort(p,p+count);
        for(int i=0;i<count;i++)
            vis[i]=1;
        vis[0]=0;
        ll ans=0;
        for(int i=0;i<count;i++)
            ans+=1LL*(b/p[i]-(a-1)/p[i])*(vis[i]-num[i]);
            ll tmp=vis[i]-num[i];
            for(int j=i;j<count;j++)
                if(p[j]%p[i]==0)
                    num[j]+=tmp;
        
        printf("Case #%d: %lld\\n",++cnt,b-a+1-ans);
    
    return 0;

二进制状态压缩容斥原理:
AC代码:

#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
ll co_prime(ll n, ll m)//求1-m中有多少个数与n互质

    ll ret=0;  //结果
    vector <ll> prime;
    prime.clear();
    ll i,j;
    for(i=2;i*i<=n;i++) 
        if(n%i==0)
        
            prime.push_back(i);
            while(n%i==0)
                n/=i;
        
    
    if(n>1)
        prime.push_back(n);
    ll len=(1<<prime.size())-1;  //状态压缩的所有状态数
    ll cnt, t;
    for(i=1;i<=len;i++)
        t=1;
        cnt=0; 
        for(j=0;j<prime.size();j++)
            if(i&(1<<j))
                t*=prime[j];
                cnt++;
            
        
        if(cnt&1)
            ret+=m/t;
        else
            ret-=m/t;
    
    return m-ret;


int main()

    //freopen("input.txt","r",stdin);
    int T;
    int cases=1;
    scanf("%d",&T);
    while(T--)
        ll a,b,c;
        scanf("%lld%lld%lld",&a,&b,&c);
        printf("Case #%d: ", cases++);
        printf("%lld\\n",co_prime(c,b)-co_prime(c,a-1));
    
    return 0;

以上是关于HDU 4135 Co-prime 容斥原理的主要内容,如果未能解决你的问题,请参考以下文章

hdu4135 Co-prime容斥原理

HDU4135 Co-prime 容斥原理

hdu 4135 Co-prime (素数打表+容斥原理)

HDU - 4135 Co-prime(容斥原理)

HDU 4135 Co-prime(容斥+数论)

题解报告:hdu 4135 Co-prime(容斥定理入门)