AtCoder-abc230_g GCD Permutation 容斥
J - GCD Permutation
传送门: J - GCD Permutation
知识点:素数筛、容斥定理、gcd
题意:长度为n的一个排列a中,求满足\(gcd(i,j)!=1 且 gcd(a_i,a_j)!=1\)的i,j对数。i,j可以相同。n<=2e5
解法:
根据埃氏筛的原理,我们知道1到n的所有倍数的总数是O(n)级别的。因此,我们可以2到n枚举作为因子的k,那么他的所有倍数两两不互质。显然这种方法枚举出来的数字总数是O(n)级别。
得到了k的倍数后,已经解决了gcd(i,j)!=1的条件。如果对这些倍数位置上的数字两两判断gcd的话一定会超时,因为单单是2的倍数就有1e5,不可以跑\(n^2\)的写法。
那么我们就要快速解决在k倍位置上有多少对贡献。两个数不互质是一定有共同的因子,可以把每个数的因子分离出来,分别计数,用map存储。
如果分离出来了x个2,y个3,z个6,那么以2作为公共因子的有x(x-1)/2对,以3作为公共因子的有y(y-1)/2对。分别计入答案之后发现2,3作为因子的贡献中,6作为因子的贡献重复了,所以还要减去6的贡献z(z-1)。
以此类推,这个问题就要用容斥来解决了。质因子数量是奇数的数字加入答案,是偶数的数字从答案扣除。含有同一质因子多次的的数字跳过。因为我们先统计了质因子的答案,然后要去掉含两个不同质因子的答案,加回来含三个不同质因子的答案。。。
这样我们就解决了k为i,j因子的贡献,同理,k=2与k=3会重复计算k=6部分的贡献,所以也要再跑一边容斥。
这样跑完得到的是不含i,j相同情况的答案,再扫一遍就行了。
#include <bits/stdc++.h>
using namespace std;
#define yaqujiejie yyds
typedef long long ll;
#define int long long
const int N = 2e5+10;
vector<int>prime;//存储素数
vector<int>yz[N];//因子
vector<int>bs[N];//倍数
bool nop[N];//不是素数
bool no[N];//不可
int yzs[N];//质因数数量
void init(){
for(int i=2;i<N;i++){
if(!nop[i]){
if(i*i<N&&i*i>0)no[i*i]=1;
prime.push_back(i);
yzs[i]++;
for(int j=i*2;j<N;j+=i){
nop[j]=1;
yzs[j]++;
ll k=(ll)i*i;
if(j%k==0)no[j]=1;
}
}
yz[i].push_back(i);
bs[i].push_back(i);
for(int j=i*2;j<N;j+=i){
yz[j].push_back(i);
bs[i].push_back(j);
}
}
}
int a[N];
signed main(){
ios::sync_with_stdio(false);
init();
int n;cin>>n;
ll ans=0;
for(int i=1;i<=n;i++)cin>>a[i];
for(int k=2;k<=n;k++){
unordered_map<int,int>mp;
for(int j=0;j<bs[k].size();j++){
for(int u=0;u<yz[a[bs[k][j]]].size();u++){
mp[yz[a[bs[k][j]]][u]]++;
}
}
ll res=0;
for(auto p:mp){
if(no[p.first])continue;
if(yzs[p.first]%2==1)res+=p.second*(p.second-1)/2;
else res-=p.second*(p.second-1)/2;
}
if(no[k])continue;
if(yzs[k]%2==1)ans+=res;
else ans-=res;
}
for(int i=2;i<=n;i++)if(a[i]!=1)ans++;
cout<<ans<<"\n";
}
AtCoder-abc230_g GCD Permutation 容斥的更多相关文章
- HihoCoder - 1867: GCD (莫比乌斯容斥)
Sample Input 6 1 6 2 5 3 4 Sample Output 10 You are given a {1, 2, ..., n}-permutation a[1], a[2], . ...
- HDU 1695 GCD(容斥定理)
GCD Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submis ...
- ZOJ 3868 GCD Expectation (容斥+莫比乌斯反演)
GCD Expectation Time Limit: 4 Seconds Memory Limit: 262144 KB Edward has a set of n integers {a1 ...
- E - Sum of gcd of Tuples (Hard) Atcoder 162 E(容斥)
题解:这个题目看着挺吓人的,如果仔细想想的话,应该能想出来.题解还是挺好的理解的. 首先设gcd(a1,a2,a3...an)=i,那么a1~an一定是i的倍数,所以ai一共有k/i种取值.有n个数, ...
- hdu 1695 GCD(容斥)
题目链接 #include <bits/stdc++.h> using namespace std; typedef long long ll; inline int read() { , ...
- Codeforces 585E. Present for Vitalik the Philatelist(容斥)
好题!学习了好多 写法①: 先求出gcd不为1的集合的数量,显然我们可以从大到小枚举计算每种gcd的方案(其实也是容斥),或者可以直接枚举gcd然后容斥(比如最大值是6就用2^cnt[2]-1+3^c ...
- HDU 1695 GCD 容斥
GCD 题目连接: http://acm.hdu.edu.cn/showproblem.php?pid=1695 Description Given 5 integers: a, b, c, d, k ...
- hdu 1695 GCD 容斥+欧拉函数
题目链接 求 $ x\in[1, a] , y \in [1, b] $ 内 \(gcd(x, y) = k\)的(x, y)的对数. 问题等价于$ x\in[1, a/k] , y \in [1, ...
- GCD HDU - 1695 (欧拉 + 容斥)
GCD Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submiss ...
- HDU 5656 CA Loves GCD (容斥)
题意:给定一个数组,每次他会从中选出若干个(至少一个数),求出所有数的GCD然后放回去,为了使自己不会无聊,会把每种不同的选法都选一遍,想知道他得到的所有GCD的和是多少. 析:枚举gcd,然后求每个 ...
随机推荐
- Java课堂学习总结
对于Java字段的初始化来说,共有以下几种方法: 1.类的构造函数(构造方法):当创建一个对象时,其构造函数就会自动调用.构造方法必须与类名相同,无返回值.如果程序员没有定义一个构造函数时,系统会自动 ...
- express的使用:路由、中间件(二)
13.路由 1.express中的路由指客户端的请求与服务器处理函数间的映射关系 2.express中的路由由请求的类型,请求的URL地址,处理函数组成 3.app.METHOD(PATH,HANDL ...
- 【IDEA】测试类(test)的模板及定义
人和动物的区别是:能制造和使用工具.因为,工具大大便利了我们的生活. 我们在使用Idea开发java项目的过程中,有些代码是固定的,我们能不能只写几个字,就代表一连串的代码.例如,这里,我们只是输入了 ...
- 逆向学习物联网-网关ESP8266-04系统联合调试
1.测试平台原理 2.搭建硬件测试平台 3.软件测试平台 1)串口终端 2)串口监视 3)OneNET后台服务 https://open.iot.10086.cn/passport/login/ 户名 ...
- FFmpeg 命令行
FFmpeg命令行帮助 #>ffmpeg -h #>ffmpeg -h long #>ffmpeg -h full 将视频按照指定的宽高输出 #>ffmpeg -i input ...
- labwindows/cvi activex 控件无法正常使用问题解决
在进行labwindows/cvi编程时,想使用时间控件,需要在界面上点击右键的activex选项中选择Microsoft Data and Time picker control6.0(SP4).如 ...
- CF960G
首先我们考虑$n$的情况,显然以$n$为分界线可以将整个序列分成两部分,就像这样: . 那么我们考虑:在这个东西前面才会有前缀最大的统计,在这个东西后面才会有后缀最大的统计 这样就剩下了$n-1$个元 ...
- Python基础数据类型-list(列表)
a = [1, 2, 3] a.append([1, 4]) a.append(8) a.append([8, 9, '10']) # 添加的是整体,即:将输入对象添加到列表末尾 print(a) # ...
- python学习(day4)
1.selenium库 import selenium #使用selenium跳过登陆 '''selenium pip install selenium ''' from selenium impor ...
- 运行不出来真的QAQ
学C的时候最大的苦恼是编译不通过和运行不正确 学了C++之后就开始有编译过了但运行不出来的情况了TAT