hdu4135-Co-prime & Codeforces 547C Mike and Foam (容斥原理)

hdu4135

求[L,R]范围内与N互质的数的个数。

分别求[1,L]和[1,R]和n互质的个数,求差。

利用容斥原理求解。

二进制枚举每一种质数的组合,奇加偶减。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

const int N = 100005;

int fac[N], cnt;

void factor(int n) {
    cnt = 0;
    int limit = sqrt(n);

    for (int i = 2; i <= limit; ++i) {
        if (n % i == 0) fac[cnt++] = i;
        while (n % i == 0) n /= i;
    }
    if (n > 1) fac[cnt++] = n;
}

ll solve(ll x, int n) { //1~x中与n互质的数
    ll ans = 0;
    ll val;
    int num;
    //printf("cnt=%d\n", cnt);

    int st = 1<<cnt;
    for (int i = 1; i < st; ++i) {// 枚举所有情况,奇加偶减
        val = 1;
        num = 0;
        for (int j = 0; j < cnt; ++j) {
            if (i & (1<<j)) {
                val *= fac[j];
                num++;
            }
        }
        //printf(">>%d %lld %d\n", i, val, num);
        if (num & 1) ans += x/val;
        else ans -= x/val;
    }
    return x - ans;
}


int main()
{
    ll x, y;
    int n;
    int t, cas=0; cin >> t;
    while (t--) {
        cin >> x >> y >> n;
        cout << "Case #" << ++cas << ": ";
        factor(n);
        cout << solve(y,n) - solve(x-1,n) << endl;
    }

    return 0;
}

 

Codeforces 547C Mike and Foam

差不多啦

求新加入的数和已经存在的数有多少是不互质的。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>

using namespace std;

const int N = 500005;
int a[N], vis[N], fac[N], tfac[N];
int n, m, q, tot;

void getfactor(int x, int fac[], int &cnt) {
    int limit = sqrt(x);
    cnt = 0;
    for (int i = 2; i <= limit; ++i) {
        if (x % i == 0) {
            fac[cnt++] = i;
            while (x % i == 0) x /= i;
        }
    }
    if (x > 1) fac[cnt++] = x;
}

int add(int x, int d) {
    int cnt;
    getfactor(x, tfac, cnt);
    int st = 1<<cnt;
    int ans = 0;
    for (int i = 1; i < st; ++i) {
        int num = 0;
        int tmp = 1;
        for (int j = 0; j < cnt; ++j) {
            if (i & (1<<j)) {
                num++;
                tmp *= tfac[j];
            }
        }
        if (d == -1) fac[tmp]--;
        if (num & 1) ans += fac[tmp];
        else ans -= fac[tmp];
        if (d == 1) fac[tmp]++;
    }
    if (d == -1) return -tot+ans;
    else return tot-1-ans;
}

int main()
{
    while (~scanf("%d%d", &n, &m)) {
        memset(vis, 0, sizeof vis);
        tot = 0;
        for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
        long long ans = 0 ,tmp;
        while (m--) {
            scanf("%d", &q);
            if (vis[q]) vis[q] = 0, tot--, tmp = add(a[q], -1);
            else vis[q] = 1, tot++, tmp = add(a[q], 1);
            ans += tmp;
            printf("%lld\n", ans);
        }
    }
    return 0;
}

 

posted @ 2016-10-14 14:21  我不吃饼干呀  阅读(410)  评论(0编辑  收藏  举报