首页 > 代码库 > 1439 互质对

1439 互质对

1439 互质对

题目来源: CodeForces
基准时间限制:2 秒 空间限制:131072 KB

有n个数字,a[1],a[2],…,a[n]。有一个集合,刚开始集合为空。然后有一种操作每次向集合中加入一个数字或者删除一个数字。每次操作给出一个下标x(1 ≤ x ≤ n),如果a[x]已经在集合中,那么就删除a[x],否则就加入a[x]。

问每次操作之后集合中互质的数字有多少对。

注意,集合中可以有重复的数字,两个数字不同当且仅当他们的下标不同。

比如a[1]=a[2]=1。那么经过两次操作1,2之后,集合之后存在两个1,里面有一对互质。

Input
单组测试数据。第一行包含两个整数n 和 q (1 ≤ n, q ≤ 2 × 10^5)。表示数字的种类和查询数目。第二行有n个以空格分开的整数a[1],a[2],…,a[n] (1 ≤ a[i] ≤ 5 × 10^5),分别表示n个数字。接下来q行,每行一个整数x(1 ≤ x ≤ n),表示每次操作的下标。
Output
对于每一个查询,输出当前集合中互质的数字有多少对。
Input示例
样例输入15 61 2 3 4 6123451样例输入22 31 1121
Output示例
样例输出1013562样例输出2010
思路:容斥原理;求容斥每个数与其他数不互质的对数,然后sum+总的再减去不互质的即可;
  1 #include<stdio.h>  2 #include<algorithm>  3 #include<iostream>  4 #include<stdlib.h>  5 #include<queue>  6 #include<string.h>  7 #include<set>  8 #include<map>  9 #include<math.h> 10 using namespace std; 11 typedef long long LL; 12 bool flag[600005]; 13 LL cnt[600005]; 14 int ff[600005]; 15 bool prime[600005]; 16 LL sum = 0; 17 int b[20]; 18 int bns[600005]; 19 int ans[600000]; 20 int n; 21 void slove(int x,int v); 22 int main(void) 23 { 24         int q; 25         scanf("%d %d",&n,&q); 26         memset(cnt,0,sizeof(cnt)); 27         memset(flag,0,sizeof(flag)); 28         int i,j;int cn = 0; 29         for(i = 2; i < 1000; i++) 30         { 31                 if(!prime[i]) 32                 { 33                         for(j = i; ((LL)i*(LL)j) <= 500000; j++) 34                         { 35                                 prime[i*j] = true; 36                         } 37                 } 38         } 39         for(i = 2;i < 500000; i++) 40         { 41             if(!prime[i]) 42             { 43                 ans[cn++] = i; 44             } 45         } 46         for(i = 0;i < cn ;i++) 47         { 48             for(j = 1;ans[i]*j <= 500000;j++) 49             { 50                 ff[ans[i]*j] = ans[i]; 51             } 52         } 53         for(i = 0; i < n; i++) 54         { 55                 int x; 56                 scanf("%d",&bns[i]); 57         } 58         n = 0; 59         while(q--) 60         { 61                 int x; 62                 scanf("%d",&x); 63                 int id = x; 64                 x = bns[x-1]; 65                 { 66                         slove(x,id); 67                 } 68                 printf("%lld\n",sum); 69         } 70         return 0; 71 } 72 void slove(int x,int v) 73 { 74         int fl = 0; 75         if(flag[v]) 76         { 77                 flag[v]=false; 78                 n--; 79                 sum-=n; 80                 fl = 1; 81         } 82         else 83         { 84                 flag[v]=true; 85                 sum += n; 86                 n++; 87         }//printf("%d\n",sum); 88         int c = x; 89         int cn = 0; 90         while(c>1) 91         { 92                 if(cn==0) 93                 { 94                         b[cn++] = ff[c]; 95                 } 96                 else if(b[cn-1]!=ff[c]) 97                 { 98                         b[cn++] = ff[c]; 99                 }100                 c/=ff[c];101         }102         if(fl)103         {104                 int i ,j;105                 for(i = 1; i < (1<<cn); i++)106                 {107                         int ac = 1;108                         int t = 0;109                         for(j = 0; j < cn; j++)110                         {111                                 if(i&(1<<j))112                                 {113                                         t++;114                                         ac*=b[j];115                                 }116                         }117                         if(t%2)118                         {119                                 cnt[ac]--;120                                 sum += cnt[ac];121                         }122                         else123                         {124                                 cnt[ac]--;125                                 sum -= cnt[ac];126                         }127                 }128         }129         else130         {131                 int i ,j;132                 for(i = 1; i < (1<<cn); i++)133                 {134                         int ac = 1;135                         int t = 0;136                         for(j = 0; j < cn; j++)137                         {138                                 if(i&(1<<j))139                                 {140                                         t++;141                                         ac*=b[j];142                                 }143                         }144                         if(t%2)145                         {146                                 sum -= cnt[ac];147                                 cnt[ac]++;148                         }149                         else150                         {151                                 sum += cnt[ac];152                                 cnt[ac]++;153                         }154                 }155         }156 }

 

 

1439 互质对