Codeforces 803F Coprime Subsequences (容斥)
Link:http://codeforces.com/contest/803/problem/F
题意:给n个数字,求有多少个GCD为1的子序列。
题解:容斥!比赛时能写出来真是炒鸡开森啊!
num[i]: 有多少个数字是 i 的倍数。
所有元素都是1的倍数的序列有:$2^n-1$个。先把$2^n-1$设为答案
所有元素都是质数的倍数的序列有:$\sum 2^{num[p_1]} - 1$个,这些序列不存在的,得从答案中减去。
所有元素都是两质数之积的倍数的序列有:$\sum 2^{num[p_1*p_2]} - 1$个,这些序列两次扫黄都在现
场,我们应减一次,但实际减了两次,多减了一次,所以要加回到答案中。
然后考虑,所有元素都是3,4,5......个质数之积的倍数的序列。
依次类推。于是就可以容斥了。
PS: 要先预处理好一个数字,能被拆成几个素数之积。而且同一个素数不能出现两次或以上。
【不优雅の】code:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
typedef long long ll;
const int MAXN = 100000+10;
const int MAXM = 100000+10;
ll prime[MAXN+1];
ll ct[MAXN], sgn[MAXN];
ll n, a[MAXN], bad[MAXN];
void getPrim()
{
memset(sgn, 1, sizeof(sgn));
memset(prime, 0, sizeof(prime));
for(int i=2;i<=MAXN;i++)
{
if(!prime[i]){
prime[++prime[0]] = i;
}
for(int j=1;(j<=prime[0])&&(prime[j]<=(MAXN/i));j++)
{
prime[prime[j]*i] = 1;
if(i%prime[j]==0) break;
}
}
} void getFactor(ll x)
{
ll cnt = 0, i;
ll tmp = x;
for(i = 1; prime[i] * prime[i] <=tmp ;i++)
{
if(tmp % prime[i] == 0)
{
int c = 0;
while(tmp % prime[i] == 0)
{
c ++;
tmp /= prime[i];
}
if(c >= 2)
{
bad[x] = 1;
return;
}
cnt ++;
}
}
if(tmp!=1)
{
cnt ++;
}
ct[x] = cnt;
} const ll MOD = 1000000007;
ll mpow(ll a, ll n)
{
ll ret = 1;
while(n)
{
if(n & 1)
{
ret = (ret * a);
ret %= MOD;
}
a = a * a % MOD;
n >>= 1;
}
return ret;
} ll num[MAXN];
int main()
{
getPrim();
for(int i=1;i<MAXN;i++)
{
getFactor(i);
}
scanf("%lld", &n);
for(int i=1;i<=n;i++)
{
scanf("%lld", &a[i]);
for(ll j=1;j*j<=a[i];j++)
{
if(a[i]%j==0)
{
if(j*j!=a[i]) num[a[i]/j] ++;
num[j] ++;
}
}
}
ll ans = 0;
for(int i=2;i<MAXN;i++)
{
if(num[i]>0 && ct[i]>0 && !bad[i])
{
//cout << i << " " << num[i] << " " << ct[i] << endl;
ans += (ll)( (ct[i]%2==1)?(1):(-1) ) * (mpow(2, num[i])-1);
ans %= MOD;
}
}
ans = (mpow(2, n) - ans + MOD) % MOD;
cout << (ans-1+MOD)%MOD << endl;
}
官方题解提到了莫比乌斯函数,最终答案的表示为$\sum\limits_{i=1}^{1e5} µ(i)(2^{num[i]}-1)$
套了下KuangBin巨巨的模板。重写了遍。
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
const int NICO = 100000+2;
const int MOD = 1000000000 + 7;
LL n, a[NICO], cnt[NICO], po[NICO], mo[NICO];
bool chk[NICO];int prime[NICO];
void init()
{
po[0] = 1, mo[1] = 1;
for(int i=1;i<NICO;i++) po[i] = 2*po[i-1]%MOD;
memset(chk, 0, sizeof(chk));
int tot = 0;
for(int i=2;i<NICO;i++)
{
if(!chk[i])
{
prime[tot++] = i;
mo[i] = -1;
}
for(int j=0;j<tot;j++)
{
if(i*prime[j]>=NICO) break;
chk[i*prime[j]] = 1;
if(i%prime[j] == 0)
{
mo[i*prime[j]] = 0;
break;
} else {
mo[i*prime[j]] = -mo[i];
}
}
}
for(int i=1;i<=n;i++)
{
for(int j=1;j*j<=a[i];j++)
{
if(a[i]%j) continue;
if(j*j != a[i]) cnt[a[i]/j] ++;
cnt[j] ++;
}
}
} int main()
{
scanf("%lld", &n);
for(int i=1;i<=n;i++) scanf("%lld", &a[i]);
LL ans = 0; init();
for(int i=1;i<NICO;i++)
{
ans = (ans + mo[i] * (po[cnt[i]]-1) )% MOD;
}
cout << (ans+1000LL*MOD)%MOD << endl;
}
Codeforces 803F Coprime Subsequences (容斥)的更多相关文章
- Codeforces 803F - Coprime Subsequences(数论)
原题链接:http://codeforces.com/contest/803/problem/F 题意:若gcd(a1, a2, a3,...,an)=1则认为这n个数是互质的.求集合a中,元素互质的 ...
- CodeForces 803F Coprime Subsequences
$dp$. 记$dp[i]$表示$gcd$为$i$的倍数的子序列的方案数.然后倒着推一遍减去倍数的方案数就可以得到想要的答案了. #include <iostream> #include ...
- Codeforces 100548F - Color (组合数+容斥)
题目链接:http://codeforces.com/gym/100548/attachments 有n个物品 m种颜色,要求你只用k种颜色,且相邻物品的颜色不能相同,问你有多少种方案. 从m种颜色选 ...
- HDU 4135 Co-prime(容斥+数论)
Co-prime Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Su ...
- HDU 4135:Co-prime(容斥+二进制拆分)
Co-prime Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
- 题解报告:hdu 4135 Co-prime(容斥定理入门)
Problem Description Given a number N, you are asked to count the number of integers between A and B ...
- HDU 4135 Co-prime(容斥:二进制解法)题解
题意:给出[a,b]区间内与n互质的个数 思路:如果n比较小,我们可以用欧拉函数解决,但是n有1e9.要求区间内互质,我们可以先求前缀内互质个数,即[1,b]内与n互质,求互质,可以转化为求不互质,也 ...
- Codeforces 920G(二分+容斥)
题意: 定义F(x,p)表示的是一个数列{y},其中gcd(y,p)=1且y>x 给出x,p,k,求出F(x,p)的第k项 x,p,k<=10^6 分析: 很容易想到先二分,再做差 然后问 ...
- Hdu 5072 Coprime(容斥+同色三角形)
原题链接 题意选出三个数,要求两两互质或是两两不互质.求有多少组这样的三个数. 分析 同色三角形n个点 每两个点连一条边(可以为红色或者黑色),求形成的三条边颜色相同的三角形的个数反面考虑这个问题,只 ...
随机推荐
- [TPYBoard - Micropython 之会python就能做硬件 9] 五分种学会用TPYBoard V102 制作避障小车(升级版)
转载请注明:@小五义 http://www.cnblogs.com/xiaowuyi 欢迎加入讨论群 64770604 感谢山东萝卜电子科技公司授权 一.实验器材 1.TPYboard V102板 ...
- Maven项目搭建(二):Maven搭建SSM框架
上一章给大家讲解了如何使用Maven搭建web项目. 这次给大家介绍一下怎么使用Maven搭建SSM框架项目. 首先我们来看一下pom.xml的属性介绍: project: pom的xml根元素. p ...
- [SinGuLaRiTy] ZKW线段树
[SinGuLaRiTy-1007] Copyrights (c) SinGuLaRiTy 2017. All Rights Reserved. 关于ZKW线段树 Zkw线段树是清华大学张昆玮发明非递 ...
- Oracle的基本学习(二)—基本查询
一.基本查询语句 (1)查看当前用户 show user; (2)查看当前用户下的表 select * from tab; (3)查看员工表的结构 desc emp; (4)选择全部列 S ...
- JavaScript基础学习(七)—BOM
BOM(Browser Object Model): 浏览器对象模型.提供了独立于内容而与浏览器窗口交互的对象,BOM主要用于管理窗口和窗口之间的通讯. 一.Navigator对象 ...
- Python爬虫 Cookie的使用
Cookie,指某些网站为了辨别用户身份.进行session跟踪而储存在用户本地终端上的数据(通常经过加密) 比如说有些网站需要登录后才能访问某个页面,在登录之前,你想抓取某个页面内容是不允许的.那么 ...
- C++命名空间的解释 【转】
使用命名空间的目的是对标识符的名称进行本地化,以避免命名冲突.在C++中,变量.函数和类都是大量存在的.如果没有命名空间,这些变量.函数.类的名称将都存在于全局命名空间中,会导致很多冲突.比如,如果我 ...
- 日志框架SLF4J
1.什么是SLF4J SLF4J:Simple Logging Facade for Java,为java提供的简单日志Facade.Facade门面,更底层一点说就是接口.它允许用户以自己的喜好,在 ...
- C#图解教程-方法参数笔记(上)
一晃大学四年要过去了,期间乱点了很多技能点, 导致每一项技能都只是处于入门阶段.为了将C#作为我的主要技能,准备恶补相关姿势(知识),通过各种技术论坛的推荐,找到了<C#图解教程>这本书. ...
- 【Tomcat源码学习】-1.概述
Tomcat是用java语言开发的一个Web服务器,最近花了差不多两周时间对Tomcat 9.0源码进行了一遍学习,由于知识储备有限,也只是理解了一个大概,下面就由我来给大家分享一下我对Tomcat的 ...