1439 互质对
Posted SJY
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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\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 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 }
以上是关于1439 互质对的主要内容,如果未能解决你的问题,请参考以下文章
优化算法静电放电优化算法(ESDA)含Matlab源码 1439期