Codeforces 547C/548E - Mike and Foam 题解
Codeforces 547C/548E - Mike and Foam 题解
前置芝士 - 容斥原理
容斥原理是简单的小学奥数求多个集合的并集的算法,最基本的思想大概是如下内容:
这是一道简单例题:有\(10\)个学生喜欢唱歌,有\(15\)个学生喜欢跳舞,有\(5\)个学生两种活动都喜欢,没有不喜欢前述两种活动的学生,那么一共有多少个学生呢?
相信聪明的你已经知道答案了,答案就是由如下算式计算得来:
\]
对的,就是跟小学奥数一样。首先把喜欢唱歌或跳舞的学生都加起来,之后再减去重复计算的\(5\)个都喜欢的学生就可以了。
形式化地说(不过这里有三个集合,为了显示更多的规律):
\]
那么,如果有更多集合又该怎么算呢?其实也不难(表述可能不清楚qaq):
枚举所有集合组成的集合的子集(也就是01枚举每个集合),如果当前枚举的子集的个数是奇数,那么就加上它们交集的大小,否则(也就是偶数),就减去它们交集的大小。
形式化地说(这个应该清楚了):
\bigcup_{i=1}^{n}S_i
\vert
=
\sum_{T \subseteq U}
(-1)^{\vert T \vert - 1}
\vert
\bigcap_{E \in T}E
\vert
\]
\(S_i\)表示第\(i\)个要被求并集的集合,\(U\)表示把所有\(S_i\)作为元素的集合,\(T\)表示枚举出来的当前的\(U\)的子集,同样,\(T\)的每个元素都是一个集合,\(\vert T \vert\)表示\(T\)的包含的集合的个数,\(E\)表示如\(S_i\)一般包含普通的元素的集合。
题意
题意很简单,给你\(n\)杯啤酒,每个啤酒有数\(a_i\)和\(q\)个操作,每个查询包含一个数\(x\),表示对第\(x\)杯啤酒操作。如果这杯啤酒在架子上,就把它拿下来,否则,就放上去。之后输出当前放在架子上的啤酒里,上面的数互质的啤酒的对数,形式化地说,就是:
输出\((i,j)\)的对数,当它们满足\(i<j\)且\(\gcd(a_i,a_j)=1\),\(\gcd\)表示最大公因数。
以下把啤酒直接就叫做数字(它上面的那个标的数\(a_i\))了。
想法(口胡)
把每个数都拆成质因子序列,并把质因子当成是要求并集的集合,然后用容斥和一些数据结构就可以快速计算与当前数互质的数的个数。
做法
首先,我们把每个数都拆成它们的质因子相乘的序列,有相同的质因子就只保留其中的一个。然后,我们再维护一个数据结构(推荐std::map,方便好用),保存的是枚举出的质因子相乘得到的某一个它的因数(第一关键字),以它作为因子(除以它余\(0\))的数\(a_i\)的个数(第二关键字)。之后用容斥的方法,就可以算出每一个数当前不与它互质的在架子上的数的个数,用总数减一下就是互质的数的个数了。添加和删去数也很方便:添加时就把所有它的因子(特指用枚举质因子相乘得到的)在map里的值加上一,删除时就减去一就好了。
程序
感觉前面做法就是描述的程序写法啊(果然还是我的表述太不清楚了吧)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int n,q,cnt;//cnt表示在架子上的啤酒的个数
ll tot;//tot是当前的所有的互质的数对的数量
int a[200005];
map<int,int> mp;//保存包含某个数作为因数的数a[i]的个数
vector<int> p[200005];//把数拆成质因子序列
bool onshelf[200005];//是否在架子上
void ext(int x,vector<int> &ps){
if(x==1){//特判一就不拆了
return;
}
for(int i=2;i*i<=x;i++){
if(x%i==0){
ps.push_back(i);
while(x%i==0)x/=i;//去除重复的因子
}
}
if(x>1)ps.push_back(x);//循环完可能还会有一个因子没有分解
}
void puton(int x){//添加第x个数到架子
int res=cnt;//假设所有数都互质
for(int s=1;s<(1<<p[x].size());s++){//枚举当前使用的质因数的集合
int mt=1,bts=0;//mt为乘积,bts记录子集大小
for(int i=0;i<p[x].size();i++){
if(s&(1<<i)){
mt*=p[x][i];
bts++;
}
}//算出乘积
if(bts&1){
res-=mp[mt];
}else{
res+=mp[mt];
}//容斥,正负相反是因为前面假设都是互质的
mp[mt]++;//添加这个因子,由于枚举出的mt各不相同,所以不会重复计算
}
tot+=res;
}
void takeoff(int x){//拿走,基本同上
int res=cnt;
for(int s=1;s<(1<<p[x].size());s++){
int mt=1,bts=0;
for(int i=0;i<p[x].size();i++){
if(s&(1<<i)){
mt*=p[x][i];
bts++;
}
}
mp[mt]--;//先减去自己的那个因子,防止重复
if(bts&1){
res-=mp[mt];
}else{
res+=mp[mt];
}
}
tot-=res;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>q;
for(int i=1;i<=n;i++){
cin>>a[i];
ext(a[i],p[i]);
}
while(q--){
int x;cin>>x;
if(onshelf[x]){
cnt--;
takeoff(x);
}else{
puton(x);
cnt++;
}
onshelf[x]^=1;//作用就是取反
cout<<tot<<endl;
}
return 0;
}
感谢
感谢你看完了!我真的是很不擅长数论qaq,如果有什么写得不清楚的欢迎在下面留言~
Codeforces 547C/548E - Mike and Foam 题解的更多相关文章
- 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 ...
- codeforces #305 C Mike and Foam
首先我们注意到ai<=50w 因为2*3*5*7*11*13*17=510510 所以其最多含有6个质因子 我们将每个数的贡献分离, 添加就等于加上了跟这个数相关的互素对 删除就等于减去了跟这个 ...
- hdu4135-Co-prime & Codeforces 547C Mike and Foam (容斥原理)
hdu4135 求[L,R]范围内与N互质的数的个数. 分别求[1,L]和[1,R]和n互质的个数,求差. 利用容斥原理求解. 二进制枚举每一种质数的组合,奇加偶减. #include <bit ...
- 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 ...
- cf#305 Mike and Foam(容斥)
C. Mike and Foam time limit per test 2 seconds memory limit per test 256 megabytes input standard in ...
- # Codeforces Round #529(Div.3)个人题解
Codeforces Round #529(Div.3)个人题解 前言: 闲来无事补了前天的cf,想着最近刷题有点点怠惰,就直接一场cf一场cf的刷算了,以后的题解也都会以每场的形式写出来 A. Re ...
- Codeforces Round #557 (Div. 1) 简要题解
Codeforces Round #557 (Div. 1) 简要题解 codeforces A. Hide and Seek 枚举起始位置\(a\),如果\(a\)未在序列中出现,则对答案有\(2\ ...
- Codeforces Round #665 (Div. 2)A-C题解
A. Distance and Axis 题目:http://codeforces.com/contest/1401/problem/A 题解:对于n来说分两种情况,一是奇数,二则是偶数 ①奇数:对于 ...
- Codeforces Round #668 (Div. 2)A-C题解
A. Permutation Forgery 题目:http://codeforces.com/contest/1405/problem/A 题解:这道题初看有点吓人,一开始居然想到要用全排序,没错我 ...
随机推荐
- MFC unicode字符集与多字节字符集 问题之彻底终结!
Unicode 和多字节字符集 (MBCS) 支持 Visual Studio .NET 2003 有些国际市场以大字符集来使用日文和中文等语言.为了支持这些市场的编程,Microsoft 基础类 ...
- wxxcx_learn异常处理
属于基础框架,分级别 捕获异常,处理异常(记录日志,修复异常,返回客户端错误),抛出异常 全局异常处理(AOP)对错误同一格式化 try{ $banner = BannerModel::getBann ...
- web漏洞-命令执行、文件上传、XSS
一.命令执行 1:什么是命令执行? 命令执行漏洞是指攻击者可以随意执行系统命令.属于高危漏洞之一任何脚本语言都可以调用操作系统命令. 应用有时需要调用一些执行系统命令的函数,举个例子如:PHP中的 ...
- CCF-CSP题解 201609-4 交通规划
最小最短路径树. \(dis[j]==dis[i]+w(i,j)\)时,从\(w(i,j')\)和\(w(i,j)\)考虑.--从0分到100分. #include <bits/stdc++.h ...
- Redis-API
Redis-API 简介 Redis 是一个基于内存的高效的键值行非关系型数据库,存取效率极高. python提供了两个类:分别为Redis和StrictRedis来实现Redis的命令操作.Redi ...
- scrapy框架(二)
scrapy框架(二) 一.scrapy 选择器 概述: Scrapy提供基于lxml库的解析机制,它们被称为选择器. 因为,它们“选择”由XPath或CSS表达式指定的HTML文档的某部分. Sca ...
- ubuntu14.04编译vim8.1
安装依赖 这一步其实我没做,直接下载编译成功了.估计有些包不是必需的.姑且列在这里供参考 sudo apt install libncurses5-dev libgnome2-dev libgnome ...
- 深入理解 Spring Cloud 核心组件与底层原理
一.Spring Cloud核心组件:Eureka Netflix Eureka Eureka详解 1.服务提供者 2.服务消费者 3.服务注册中心 二.Spring Cloud核心组件:Ribbon ...
- 基于Postman中的报错
Postman中的报错: Could not get any response 错误 Could not get any response There was an error connecting ...
- ios学习之路:Xcode+swift+打包ipa一步一坑记录
咳咳,作为公司的Android开发(兼java接口开发,兼软件测试,兼运维……)由于公司ios开发小伙伴离我而去,ios的app出了问题,急需处理.于是领导决定由我来处理一下.就是用证书重新打包的事儿 ...