HDU 4407 (容斥)

来源:互联网 发布:大张伟的姜昆女友知乎 编辑:程序博客网 时间:2024/04/30 07:21

题目链接:点击这里

题意: 给出1,2,3…n这个序列, 然后两种操作: 求某一个闭区间和p互质的数的和; 改变某一个数.

因为操作数比较少, 所以改变可以都存下来, 计算原区间的结果, 然后用存下来的改变更新下就好了. 区间互质的和可以容斥可以反演很ez.

#include <bits/stdc++.h>using namespace std;#define maxn 400005int n, m;struct node {    int id, num;    bool operator < (const node &a) const {        return id < a.id;    }    bool operator == (const node &a) const {        return id == a.id;    }};set <node> gg;set <node>::iterator it;vector <int> fac[maxn];//每一个数的素因子bool is_prime[maxn];int prime[maxn], cnt;void init () {    cnt = 0;    for (int i = 0; i < maxn; i++) fac[i].clear ();    memset (is_prime, 1, sizeof is_prime);    is_prime[0] = is_prime[1] = 0;    for (int i = 2; i < maxn; i++) if (is_prime[i]) {        prime[cnt++] = i;        fac[i].push_back (i);        for (int j = i+i; j < maxn; j += i) {            fac[j].push_back (i);            is_prime[j] = 0;        }    }}int cal (int num, int &mul, int x) {    mul = 1;    int ans = 0, Max = fac[x].size ();    for (int i = 1; i <= Max; i++, num >>= 1) {        if (num&1) {            ans++;            mul *= fac[x][i-1];        }    }    return ans;}long long solve (int pos, int num) {//[1,pos]中和num互质的数    if (pos < 1) return 0;    long long ans = 0;    int Max = (1<<fac[num].size ());    for (int i = 1; i < Max; i++) {        int mul;        int num_of_1 = cal (i, mul, num);        long long cnt = pos/mul, sum = (mul+1LL*mul*cnt)*cnt/2;        if (num_of_1&1) {            ans += sum;        }        else            ans -= sum;    }    ans = (1LL*pos+1)*pos/2-ans;    return ans;}int main () {    int t;    scanf ("%d", &t);    init ();    while (t--) {        scanf ("%d%d", &n, &m);        gg.clear ();        for (int i = 1; i <= m; i++) {            int op, x, y, num;            scanf ("%d", &op);            if (op == 1) {                scanf ("%d%d%d", &x, &y, &num);                long long ans = solve (y, num)-solve (x-1, num);                for (it = gg.begin (); it != gg.end (); it++) {                    if (it->id >= x && it->id <= y) {                        int pos = it->id, cur = it->num;                        if (__gcd (num, pos) == 1) ans -= pos;                        if (__gcd (cur, num) == 1) ans += cur;                    }                }                printf ("%lld\n", ans);            }            else {                scanf ("%d%d", &x, &y);                gg.erase ((node) {x, 0});                gg.insert ((node) {x, y});            }        }    }    return 0;}
0 0
原创粉丝点击