zoukankan      html  css  js  c++  java
  • CF585E:Present for Vitalik the Philatelist

    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的贡献呢?同理耶!

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<algorithm>
     4 #include<stdlib.h>
     5 //#include<iostream>
     6 using namespace std;
     7 
     8 int n;
     9 #define maxn 500011
    10 #define maxm 10000011
    11 const int mod=1e9+7;
    12 int a[maxn];
    13 
    14 int xiao[maxm],miu[maxm],prime[maxm],lp;bool notprime[maxm];
    15 void pre(int n)
    16 {
    17     lp=0;notprime[1]=1;
    18     for (int i=2;i<=n;i++)
    19     {
    20         if (!notprime[i]) {prime[++lp]=i;miu[i]=-1;}
    21         for (int j=1;j<=lp && 1ll*prime[j]*i<=n;j++)
    22         {
    23             notprime[prime[j]*i]=1;
    24             xiao[prime[j]*i]=prime[j];
    25             if (!(i%prime[j])) {miu[i*prime[j]]=0;break;}
    26             else miu[i*prime[j]]=-miu[i];
    27         }
    28     }
    29 }
    30 
    31 int cnt[maxm],two[maxn];
    32 int frac[15],lf;
    33 int main()
    34 {
    35     scanf("%d",&n);int Max=0;
    36     for (int i=1;i<=n;i++) scanf("%d",&a[i]),Max=max(Max,a[i]);
    37     two[0]=1;for (int i=1;i<=n;i++) two[i]=(two[i-1]<<1)%mod;
    38     pre(Max);
    39     for (int i=1;i<=n;i++)
    40     {
    41         int tmp=a[i];lf=0;
    42         while (xiao[tmp])
    43         {
    44             int now=xiao[tmp];
    45             while (xiao[tmp]==now) tmp/=xiao[tmp];
    46             frac[++lf]=now;
    47         }
    48         if (!lf || frac[lf]!=tmp) frac[++lf]=tmp;
    49         for (int i=1;i<(1<<lf);i++)
    50         {
    51             int now=1;
    52             for (int j=1;j<=lf;j++) if (i&(1<<(j-1))) now*=frac[j];
    53             cnt[now]++;
    54         }
    55     }
    56     int A=0;
    57     for (int i=2;i<=Max;i++) A=(A-miu[i]*(two[cnt[i]]-1))%mod;
    58     
    59     int ans=0;
    60     for (int i=1;i<=n;i++)
    61     {
    62         int tmp=a[i];lf=0;
    63         while (xiao[tmp])
    64         {
    65             int now=xiao[tmp];
    66             while (xiao[tmp]==now) tmp/=xiao[tmp];
    67             frac[++lf]=now;
    68         }
    69         if (!lf || frac[lf]!=tmp) frac[++lf]=tmp;
    70         int B=0;
    71         for (int i=1;i<(1<<lf);i++)
    72         {
    73             int now=1;
    74             for (int j=1;j<=lf;j++) if (i&(1<<(j-1))) now*=frac[j];
    75             B=(B-miu[now]*(two[cnt[now]]-1))%mod;
    76         }
    77         ans=((ans+A)%mod-B)%mod;
    78     }
    79     printf("%d
    ",(ans+mod)%mod);
    80     return 0;
    81 }
    View Code
  • 相关阅读:
    字符串比较
    LOOP AT SCREEN
    Trunc的日期用法
    【ABAP】SELECT-ENDSELECT尽量不要用
    【转】Abap For all entries in 使用
    01如何创建sequence:
    abap --MOVE-CORRESPONDING
    Abap 常用变量
    StringBuffer的用法
    Spring事务的传播方式
  • 原文地址:https://www.cnblogs.com/Blue233333/p/7920138.html
Copyright © 2011-2022 走看看