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示例
样例输入1
5 6
1 2 3 4 6
1
2
3
4
5
1
样例输入2
2 3
1 1
1
2
1
Output示例
样例输出1
0
1
3
5
6
2
样例输出2
0
1
0
思路:容斥原理;求容斥每个数与其他数不互质的对数,然后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
",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
",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                         else
123                         {
124                                 cnt[ac]--;
125                                 sum -= cnt[ac];
126                         }
127                 }
128         }
129         else
130         {
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                         else
150                         {
151                                 sum += cnt[ac];
152                                 cnt[ac]++;
153                         }
154                 }
155         }
156 }
 
油!油!you@
原文地址:https://www.cnblogs.com/zzuli2sjy/p/5867895.html