http://codeforces.com/problemset/problem/548/E

这题是询问id,如果这个id不在,就插入这个id,然后求a[id1] ,  a[id2]互质的对数。

询问有多少个互质这个套路出了很多次,这次是在线

首先维护当前的ans,可以知道每一步的ans,都是由于上一步的ans递推过来的。就是小答案可以由大答案推过来。

就是现在数组是a[] = 1, 2, 3,维护一个ans表示有多少对gcd等于1,然后添加一个4,只需要询问4在a[] = {1, 2, 3}中有多少个和它互质,即可。

(有时候也需要总体分析。-  - ,与这题无关)

分析:

怎么说呢,很久之后我看到这题,发现压根就没写详解,虽然自己记得具体解法,但是却没理论论证。想了一晚,现在回忆起来了。

难点就是在于给定一个集合,然后给你一个数,问这个集合里面有多少个数与它互质。

比如现在集合是:4、6、8、9、11

询问数字:12

与它gcd = 1, 相当于  size - (gcd != 1)对立面。

设gcd[i]表示与查询数gcd = i的总数

然后就是相当于  size -  (gcd[2] + gcd[3] + gcd[4] + gcd[5] + ..... + gcd[12])

然后这样很明显会是减多了。比如gcd[6],会在gcd[2]的时候减一次,gcd[3]减一次,gcd[6]减一次。这样相当于减了3次。

所以每个gcd[i]前面应该还有一个系数控制它减多少。这个系数嘛,就是mobius[i],这个就不说啦,当我们都懂了。就是gcd的容斥。

比如mobius[4] = 0,因为gcd[4]会在gcd[2]和gcd[4]的时候各减去一次,同时需要保留一次,就保留了gcd = 2的,(mobius[2] = -1)

而mobius[6] = 1,因为gcd[6],会在gcd[2]的时候减一次,gcd[3]减一次,gcd[6]减一次。这样相当于减了3次。那么如果在gcd[6]的时候加回一次,就相当于减去了一次而已。满足条件。

回到题目,如果每次都和上面这样做,复杂度O(val),因为要枚举2----val之间的数字。

但是有很多东西是不必要的枚举,比如枚举gcd[7],根本没有数字可能与12  gcd = 7

所以只需要枚举12的因子即可,12 = 2 * 2 * 3,因子有2、3、4、6、12,每个因子是加是减,也是由Mobius[i]决定。

但是这样枚举也很多的哦,

首先知道没必要枚举4,因为mobius[4] = 0,也没必要枚举12,同理mobius[12] = 0

那么把12写成     12 = 2 * 3,就是每个质因子出现的次数只保留一次,然后有约数是2、3、6,去容斥即可,奇加偶减

做到了每个数字的mobius[i]都 != 0,枚举都是有必要的。

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
const int maxn = + ;
int prime[maxn][], a[maxn];
void init() {
for (int i = ; i <= maxn - ; ++i) {
if (prime[i][]) continue;
for (int j = i; j <= maxn - ; j += i) {
prime[j][++prime[j][]] = i;
}
}
// prime[1][0] = 1;
// prime[1][1] = 1;
}
bool in[maxn];
int num[maxn];
void maintain(int val, int op) {
int en = ( << prime[val][]) - ;
for (int i = ; i <= en; ++i) {
int res = ;
for (int j = ; j <= prime[val][]; ++j) {
if (i & ( << (j - ))) res *= prime[val][j];
}
num[res] += op;
}
}
LL ans;
LL getAns(int val) {
LL ans = ;
int en = ( << prime[val][]) - ;
for (int i = ; i <= en; ++i) {
int res = ;
int sel = ;
for (int j = ; j <= prime[val][]; ++j) {
if (i & ( << (j - ))) {
++sel;
res *= prime[val][j];
}
}
if (sel & ) ans += num[res];
else ans -= num[res];
}
return ans;
}
void work() {
int n, q, tot = ;
scanf("%d%d", &n, &q);
for (int i = ; i <= n; ++i) scanf("%d", a + i);
for (int i = ; i <= q; ++i) {
int id;
scanf("%d", &id);
if (in[id]) {
maintain(a[id], -);
in[id] = false;
ans -= getAns(a[id]);
tot--;
} else {
ans += getAns(a[id]);
maintain(a[id], );
in[id] = true;
tot++;
}
printf("%I64d\n", 1LL * tot * (tot - ) / - ans);
}
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
init();
// int val = 4;
// for (int i = 1; i <= prime[val][0]; ++i) {
// printf("%d ", prime[val][i]);
// }
// printf("\n");
work();
return ;
}

http://www.cnblogs.com/liuweimingcprogram/p/6919379.html

E. Mike and Foam 容斥原理的更多相关文章

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

    hdu4135 求[L,R]范围内与N互质的数的个数. 分别求[1,L]和[1,R]和n互质的个数,求差. 利用容斥原理求解. 二进制枚举每一种质数的组合,奇加偶减. #include <bit ...

  2. E. Mike and Foam(容斥原理)

    E. Mike and Foam Mike is a bartender at Rico's bar. At Rico's, they put beer glasses in a special sh ...

  3. Codeforces 547C/548E - Mike and Foam 题解

    目录 Codeforces 547C/548E - Mike and Foam 题解 前置芝士 - 容斥原理 题意 想法(口胡) 做法 程序 感谢 Codeforces 547C/548E - Mik ...

  4. cf#305 Mike and Foam(容斥)

    C. Mike and Foam time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...

  5. Codeforces548E:Mike and Foam

    Mike is a bartender at Rico's bar. At Rico's, they put beer glasses in a special shelf. There are n  ...

  6. Codeforces 548E Mike ans Foam (与质数相关的容斥多半会用到莫比乌斯函数)

    题面 链接:CF548E Description Mike is a bartender at Rico's bar. At Rico's, they put beer glasses in a sp ...

  7. Mike and Foam(位运算)

    English reading: bartender == barmaid:酒吧女招待 milliliter:毫升:千分之一毫升 foam:泡沫 a glass of beer with a good ...

  8. codeforces #305 C Mike and Foam

    首先我们注意到ai<=50w 因为2*3*5*7*11*13*17=510510 所以其最多含有6个质因子 我们将每个数的贡献分离, 添加就等于加上了跟这个数相关的互素对 删除就等于减去了跟这个 ...

  9. codeforces 547c// Mike and Foam// Codeforces Round #305(Div. 1)

    题意:给出数组arr和一个空数组dst.从arr中取出一个元素到dst为一次操作.问每次操作后dst数组中gcd等于1的组合数.由于数据都小于10^6,先将10^6以下的数分解质因数.具体来说从2开始 ...

随机推荐

  1. 【Codeforces】Gym 101156G Non-Attacking Queens 打表

    题意 求$n\times n$的棋盘上放$3$个皇后使得互相不攻击的方案数 拓展是$m\times n$棋盘上放$k$皇后,暴力打表找到了公式 OEIS 代码 import java.math.Big ...

  2. linux命令学习:echo详解,格式化输出,不换行输出

    shell脚本不换行刷新数据 #!/bin/bash ] do a=$(ifconfig eth0 | grep 'RX pac' | awk '{print $2}' | awk -F: '{pri ...

  3. BZOJ3230 相似子串[后缀数组+二分+st表]

    BZOJ3230 相似子串 给一个串,查询排名i和j的子串longest common suffix和longest common prefix 思路其实还是蛮好想的,就是码起来有点恶心.可以发现后缀 ...

  4. ACM学习历程—Hihocoder 1164 随机斐波那契(数学递推)

    时间限制:5000ms 单点时限:1000ms 内存限制:256MB 描述 大家对斐波那契数列想必都很熟悉: a0 = 1, a1 = 1, ai = ai-1 + ai-2,(i > 1). ...

  5. bzoj 3771: Triple 快速傅里叶变换 FFT

    题目大意: 给出\(n\)个互不相同的物品,每个物品有价值\(x_i(x_i \leq 40000)\)如果可以从中取一个或两个或三个物品.问能够组合出来的所有价值和对应的方案数,全部输出.取值时,\ ...

  6. 前端PHP Session的实例

    登陆例子:(请注意一定要自己敲一遍,不要CV大法) 首先上一下成果图,激起同学们写的欲望,登录页如下:  点击登陆之后如下: 说明哦了,么问题.接下来自己实现一下. 首先数据库信息: 新建一个名为 l ...

  7. zynq基础

    zynq交叉编译环境设置 OpenCV在Zedboard上的移植 ubuntu 下串口调试工具 minicom安装与配置

  8. Hibernate延迟加载与opensessioninviewFilter

    转自:https://blog.csdn.net/skk_7/article/details/17917339 hibernate延迟加载: 一个person对应多个school,使用hibernat ...

  9. string行读入&&文件输入

    普通读入的时候会以空格作为分隔符 直接用cin>>s读入,此时可以直接处理文件尾的情况 text代码: #include <iostream>#include <cstd ...

  10. 打包python文件为exe文件(PyInstaller工具使用方法)

    最近做的新浪微博爬虫程序,打算打包成.exe软件以方便使用,网上找到一个很好的打包工具pyinstaller,这里记录一下打包的方法. 一.下载pyinstaller 我使用的版本为PyInstall ...