avatar
fireworks99
keep hungry keep foolish

HDU 4135 Co-prime 容斥原理

Description

给出区间[L, R],给出数字N,求在该区间里与N互质的数字的个数

Analyze

在区间[L, R]里与N互质的数字的个数

== 在区间[1, R]里与N互质的数字的个数

减去( - ) 在区间[1, L]里与N互质的数字的个数

所以可以自定义一个函数求出[1, up]里与N互质的数的个数

但是数字太多,依次找互质的数字不好找,但找不互质的容易

区间[1, up]里N的质因子的倍数与N不互质

找到一个质因子可找到一大堆它的倍数(与N不互质的数字)

像找2、3、5…的倍数时有重复(6,10,15),这便用到容斥!

Code

#include <map>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll long long

ll factor[100005], cnt = 0;

void get_factors(ll n)///①得到全集②进行容斥
{
    cnt = 0;
    for(ll i = 2; i * i <= n; ++i)
    {
        if(n % i == 0)
        {
            factor[cnt++] = i;
            while(n % i == 0)
                n /= i;
        }
    }
    if(n != 1)
        factor[cnt++] = n;
}

ll Rongchi_queue(ll up)///计算 1 ~ up 内有几个 与n不互质(n)
{
    ll t = 0, q[100005], res = 0;
    q[t++] = -1;
    for(ll i = 0; i < cnt; ++i)
    {
        ll up = t;
        for(ll j = 0; j < up; ++j)
            q[t++] = q[j] * factor[i] * -1;
    }
    for(ll i = 1; i < t; ++i)
        res += up / q[i];
    return res;
}

ll Rongchi_binary(ll up)
{
    ll res = 0;
    for(ll i = 1; i < (1 << cnt); ++i)
    {
        ll tem = 1, tot = 0;
        for(ll j = 0; j < cnt; ++j)
            if(i & (1 << j))
            {
                tot++;
                tem *= factor[j];
            }
        if(tot & 1)
            res += up / tem;
        else
            res -= up / tem;
    }
    return res;
}

ll sum = 0;
void DFS(ll num, ll used, ll up, ll mu, ll sth)
{
    if(used == up)
    {
        sum += sth / mu;
        return;
    }
    if(num == cnt)
        return ;
    DFS(num + 1, used, up, mu, sth);
    DFS(num + 1, used + 1, up, mu * factor[num], sth);
}

ll Rongchi_DFS(ll up)
{
    ll res = 0;
    for(ll i = 1; i <= cnt; ++i)
    {
        sum = 0;
        DFS(0, 0, i, 1, up);
        if(i & 1)
            res += sum;
        else
            res -= sum;
    }
    return res;
}

int main()
{
    int t, tot = 1;
    ll left, right, n;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%lld%lld%lld", &left, &right, &n);
        get_factors(n);
//        ll ans = Rongchi_queue(right) - Rongchi_queue(left - 1);
//        ll ans = Rongchi_binary(right) - Rongchi_binary(left - 1);
        ll ans = Rongchi_DFS(right) - Rongchi_DFS(left - 1);
        ans = right - (left - 1) - ans;
        cout << "Case #" << tot++ << ": ";
        cout << ans << '\n';
    }
    return 0;
}
Site by Baole Zhao | Powered by Hexo | theme PreciousJoy