HDU 1695(容斥)

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define maxn 111111

int c, d, a, b, k;
vector <int> gg[maxn];
bool is_prime[maxn];
int cnt, prime[maxn];

void get_prime () { //分解1-100000所有的数
    for (int i = 1; i <= 100000; i++)
        gg[i].clear();
    memset (is_prime, 1, sizeof is_prime);
    is_prime[0] = is_prime[1] = 0;
    cnt = 0;
    for (int i = 2; i <= 100000; i++) {
        if (is_prime[i]) {
            prime[++cnt] = i;
            gg[i].push_back (i);
            for (int j = i+i; j <= 100000; j += i) {
                is_prime[j] = 0;
                gg[j].push_back (i);
            }
        }
    }
}

int count (int num, long long &mul, int x) {
    mul = 1;
    int ans = 0;
    int Max = gg[x].size ();
    for (int i = 1; i <= Max; i++, num >>= 1) {
        if (num&1) {
            mul *= gg[x][i-1];
            ans++;
        }
    }
    return ans;
}

long long solve () {//[1,b], [1,d]
    long long ans = 0;
    for (int x = 1; x <= d; x++) { //求[1,min(b,x)]中和x不互质的个数
        int r = min (b, x);
        long long cur = 0, mul;
        for (int i = 1; i < (1<<gg[x].size ()); i++) {
            int num_of_1 = count (i, mul, x); //二进制i中1的个数
            if (num_of_1&1)
                cur += r/mul;
            else cur -= r/mul;
        } 
        ans += (r-cur);
    }
    return ans;
}

int main () {
    int t, kase = 0;
    cin >> t;
    get_prime ();
    while (t--) {
        cin >> a >> b >> c >> d >> k;
        if (k == 0) {
            printf ("Case %d: 0\n", ++kase);
            continue;
        }
        b /= k, d /= k;
        if (d < b)
            swap (d, b);
        printf ("Case %d: %lld\n", ++kase, solve ());
    }
    return 0;
}

你可能感兴趣的:(容斥,hdu1695)