1. 程式人生 > >hdu 4135 Co-prime 【容斥定理應用】

hdu 4135 Co-prime 【容斥定理應用】

題目連結:http://acm.hdu.edu.cn/showproblem.php?pid=4135

容斥定理求一個區間內與n互素的數有幾個;

和模板差不多,只是區間 [1,R] 變成 [L,R],所以可以求出 [1,L] 和 [1,R] 的互素的數的shu'lian再相減,注意這道題的範圍;

關於容斥定理的詳解  我推薦這篇部落格:https://blog.csdn.net/m0_37286282/article/details/78869512#t6

先給出模板:

int solve (int n, int r)
{
    vector<int> p;
    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);
    int sum = 0;
    for (int msk=1; msk<(1<<p.size()); ++msk)
    {
        int mult = 1,
            bits = 0;
        for (int i=0; i<(int)p.size(); ++i)
            if (msk & (1<<i))
            {
                ++bits;
                mult *= p[i];
            }
        int cur = r / mult;
        if (bits % 2 == 1)
            sum += cur;
        else
            sum -= cur;
    }
    return r - sum;
}

這是AC程式碼:

#include<stdio.h>
#include<string.h>
#include<string>
#include<queue>
#include<stack>
#include<map>
#include<vector>
#include<set>
#include<algorithm>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N=1e5+10;

vector<ll>p;

ll solve(ll l,ll r,ll n)
{
    p.clear();
    for(ll 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);
    ll suma=0,sumb=0;
    for(int i=1;i<(1<<p.size());++i)
    {
        ll k=0;
        ll pa=1,pb=1;
        for(int j=0;j<p.size();++j)
        {
            if(i&(1<<j))
            {
                k++;
                pa*=p[j];
                pb*=p[j];
            }
        }
        pa=l/pa;
        pb=r/pb;
        if(k%2==1)
            suma+=pa,sumb+=pb;
        else
            suma-=pa,sumb-=pb;
    }
    return sumb-suma;
}

int main()
{
    int T,cal=0;
    scanf("%d",&T);
    while(T--)
    {
        ll l,r,n;
        scanf("%lld %lld %lld",&l,&r,&n);
        l--;
        printf("Case #%d: %lld\n",++cal,r-l-solve(l,r,n));
    }
    return 0;
}