B - Co-prime
参考:HDU 4135 Co-prime (容斥原理)

这个题利用的是容斥原理,同时也利用到了求质数个数的一个技巧—— 1~m 内与 n 不互质的个数为 m/n 个:

prime.clear();
    for(ll i=2;i*i<=n;++i)
    {
        if(n%i==0)
            prime.emplace_back(i);
        while (n%i==0)
            n/=i;
    }
    if(n>1) prime.emplace_back(n);

同时使用容斥原理的时候求各种组合的时候利用了二进制的技巧:

ll sum=0,siz=prime.size();
    for(ll i=1;i<(1<<siz);++i)  // i 为 1 时取 prime[0],i 为 101(二进制) 时取 prime[0] prime[2]
    {
        ll val=1,cnt=0;
        for(ll j=0;j<siz;++j)
            if(i&(1<<j))
                val*=prime[j],cnt++;
        if(cnt&1) sum+=x/val;
        else sum-=x/val;
    }

代码(记得 long long .....因为这个 WA 了一发):

// Created by CAD on 2019/8/10.
#include <bits/stdc++.h>
using namespace std;
using pii=pair<int, int>;
using piii=pair<pair<int, int>, int>;
using ll=long long;
vector<ll> prime;

ll cal(ll x,ll n)
{
    prime.clear();
    for(ll i=2;i*i<=n;++i)
    {
        if(n%i==0)
            prime.emplace_back(i);
        while (n%i==0)
            n/=i;
    }
    if(n>1) prime.emplace_back(n);
    ll sum=0,siz=prime.size();
    for(ll i=1;i<(1<<siz);++i)
    {
        ll val=1,cnt=0;
        for(ll j=0;j<siz;++j)
            if(i&(1<<j))
                val*=prime[j],cnt++;
        if(cnt&1) sum+=x/val;
        else sum-=x/val;
    }
    return x-sum;
}
ll a,b,n;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t;
    cin>>t;
    for(int cas=1;cas<=t;++cas)
    {
        cin>>a>>b>>n;
        cout<<"Case #"<<cas<<": "<<1ll*cal(b,n)-1ll*cal(a-1,n)<<endl;
    }
    return 0;
}