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个点 每两个点连一条边(可以为红色或者黑色),求形成的三条边颜色相同的三角形的个数反面考虑这个问题,只 ...
随机推荐
- Ubuntu 16.04系统下安装RapidSVN版本控制器及配置diff,editor,merge和exploer工具
在Window下我们使用TortoiseSVN(小乌龟),可以很方便地进行查看.比较.更新.提交.回滚等SVN版本控制操作. 在Linux下我们可以使用RapidSVN.RapidSVN是一款轻量级的 ...
- Java语言定义的线程状态分析
说到线程,一定要谈到线程状态,不同的状态说明线程正处于不同的工作机制下,不同的工作机制下某些动作可能对线程产生不同的影响. Java语言定义了6中状态,而同一时刻,线程有且仅有其中的一种状态.要获取J ...
- SQL Server 给表和字段添加说明
.添加表说明 EXECUTE sp_addextendedproperty N'MS_Description','表说明',N'user',N'dbo',N'table',N'表名',NULL,NUL ...
- Java内存泄露实例
- java中的==、equals()、hashCode()源码分析
转载自:http://www.cnblogs.com/xudong-bupt/p/3960177.html 在Java编程或者面试中经常会遇到 == .equals()的比较.自己看了看源码,结合实际 ...
- 纯JS写动态分页样式效果
效果图如下: html: <body> <div> <table id="btnbox"> <tbody> <tr>&l ...
- MVC 5 + EF6 完整教程15 -- 使用DI进行解耦
如果大家研究一些开源项目,会发现无处不在的DI(Dependency Injection依赖注入). 本篇文章将会详细讲述如何在MVC中使用Ninject实现DI 文章提纲 场景描述 & 问题 ...
- Framework7+vue demo
最近看了下f7+vue做了几个测试页面,商品图片来自淘宝,代码等有时间了再传,
- jquery处理checkbox(复选框)是否被选中
现在如果一个复选框被选中,是用checked=true,checked="checked"也行 要用prop代替attr会更好,虽然在jQuery1.6之前版本的attr()方法能 ...
- Shiro基础学习(一)—权限管理
一.基本概念 1.权限管理 只要有用户参与的系统一般都要有权限管理,权限管理实现对用户访问系统的控制,按照安全规则或者安全策略控制用户可以访问而且只能访问自己被授权的资源. 权限管理 ...