n<=500000个2<=Ai<=1e7的数,求这样选数的方案数:先从其中挑出一个gcd不为1的集合,然后再选一个不属于该集合,且与该集合内任意一个数互质的数。

好的统计题。

其实就是要对每个数求和他互质的,gcd不为1的集合数,容斥一下,求出所有gcd不为1的集合数A然后减去所有他的质因子对这个A的贡献。(这里的A是CF的题解的B)

那先看看所有gcd不为1的集合数怎么求。比如说2的倍数有cnt_2个,那能凑出2^cnt_2-1个集合,然后3的倍数有cnt_3个,能凑出2^cnt_3-1个集合,但有一些gcd为6的集合被算了两次,就要减去2^cnt_6-1,等等这不是莫比乌斯函数嘛,所以现在只要统计1~1e7中每个数作为多少个数的因数即可。那要把n个数都进行分解,这里可以在筛莫比乌斯的时候记一下每个数的最小质因子就可以n*logMax的时间内完成所有数的分解。由于miu_i=0的cnt_i对答案没贡献,所以每个数分解完的质因子不用去考虑那些次数大于1的部分,比如12=2*2*3直接看2和3即可。把不重复质数分解出来后,在1e7内一个数最多有8个不同质因子,所以枚举一下所有这些质因子能凑出的数即可计算miu_i不为0的cnt_i。

然后某个数的质因子对A的贡献呢?同理耶!

 #include<stdio.h>
#include<string.h>
#include<algorithm>
#include<stdlib.h>
//#include<iostream>
using namespace std; int n;
#define maxn 500011
#define maxm 10000011
const int mod=1e9+;
int a[maxn]; int xiao[maxm],miu[maxm],prime[maxm],lp;bool notprime[maxm];
void pre(int n)
{
lp=;notprime[]=;
for (int i=;i<=n;i++)
{
if (!notprime[i]) {prime[++lp]=i;miu[i]=-;}
for (int j=;j<=lp && 1ll*prime[j]*i<=n;j++)
{
notprime[prime[j]*i]=;
xiao[prime[j]*i]=prime[j];
if (!(i%prime[j])) {miu[i*prime[j]]=;break;}
else miu[i*prime[j]]=-miu[i];
}
}
} int cnt[maxm],two[maxn];
int frac[],lf;
int main()
{
scanf("%d",&n);int Max=;
for (int i=;i<=n;i++) scanf("%d",&a[i]),Max=max(Max,a[i]);
two[]=;for (int i=;i<=n;i++) two[i]=(two[i-]<<)%mod;
pre(Max);
for (int i=;i<=n;i++)
{
int tmp=a[i];lf=;
while (xiao[tmp])
{
int now=xiao[tmp];
while (xiao[tmp]==now) tmp/=xiao[tmp];
frac[++lf]=now;
}
if (!lf || frac[lf]!=tmp) frac[++lf]=tmp;
for (int i=;i<(<<lf);i++)
{
int now=;
for (int j=;j<=lf;j++) if (i&(<<(j-))) now*=frac[j];
cnt[now]++;
}
}
int A=;
for (int i=;i<=Max;i++) A=(A-miu[i]*(two[cnt[i]]-))%mod; int ans=;
for (int i=;i<=n;i++)
{
int tmp=a[i];lf=;
while (xiao[tmp])
{
int now=xiao[tmp];
while (xiao[tmp]==now) tmp/=xiao[tmp];
frac[++lf]=now;
}
if (!lf || frac[lf]!=tmp) frac[++lf]=tmp;
int B=;
for (int i=;i<(<<lf);i++)
{
int now=;
for (int j=;j<=lf;j++) if (i&(<<(j-))) now*=frac[j];
B=(B-miu[now]*(two[cnt[now]]-))%mod;
}
ans=((ans+A)%mod-B)%mod;
}
printf("%d\n",(ans+mod)%mod);
return ;
}

最新文章

  1. 贪心 Gym 100502E Opening Ceremony
  2. HDU1003 Max Sum(求最大字段和)
  3. java.util.ConcurrentModificationException 解决办法(转)
  4. 站点下的GridView的RowCommand事件的设置,与站点应用不一样
  5. MVC 中集成 AngularJS1
  6. python制作一个简单的中奖系统
  7. HTTP与HTTPs的区别?
  8. 低级sql语法错误: BadSqlGrammarException
  9. python中常用的模块二
  10. Code Signal_练习题_evenDigitsOnly
  11. FineReport8.0如何连接FineIndex取数分析
  12. 评点SAP HR功能及人力资源管理软件
  13. AC自动机技巧
  14. Node.js 介绍及安装
  15. 配置阿里云ESC服务器部署项目
  16. print to console or file
  17. pipeline构建时报错问题解决
  18. Google Java 编程风格指南 —— 见微知著
  19. linux 安装vscode
  20. centos7系统安装配置

热门文章

  1. python_基础部分(1)
  2. commons-lang常用工具类StringEscapeUtils使用--转
  3. [转]Android项目快速开发框架探索(Mysql + OrmLite + Hessian + Sqlite)
  4. iOS定位--CoreLocation框架
  5. 自制无线共享工具C++源代码及创建过程
  6. 重装macOS环境配置笔记
  7. 我用的主机,推荐给大家【gegehost】【戈戈主机】
  8. python与shell通过微信企业号发送消息
  9. 迅为i.MX6Q嵌入式开发板
  10. 编写图形界面下的Java Swing程序,接受用户输入的两个数据为上下限,然后输出上、下限之间的所有素数。(结果部分每行显示10个数据)