1678 lyk与gcd

基准时间限制:2 秒 空间限制:131072 KB

这天,lyk又和gcd杠上了。
它拥有一个n个数的数列,它想实现两种操作。


1:将  ai 改为b。
2:给定一个数i,求所有 gcd(i,j)=1 时的  aj  的总和。

Input
第一行两个数n,Q(1<=n,Q<=100000)。
接下来一行n个数表示ai(1<=ai<=10^4)。
接下来Q行,每行先读入一个数A(1<=A<=2)。
若A=1,表示第一种操作,紧接着两个数i和b。(1<=i<=n,1<=b<=10^4)。
若B=2,表示第二种操作,紧接着一个数i。(1<=i<=n)。
Output
对于每个询问输出一行表示答案。
Input示例
5 3
1 2 3 4 5
2 4
1 3 1
2 4
Output示例
9
7
思路:容斥原理;
我们用容斥将每个数的质因子,然后将其所对应的数加到表中,奇加偶减,然后分解当前的询问的数,然后可以重表中找出那些和他不互质的所对应的书数的和,然后总的减去即可。
  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<stdlib.h>
  5 #include<queue>
  6 #include<string.h>
  7 #include<math.h>
  8 #include<map>
  9 using namespace std;
 10 typedef long long LL;
 11 int ans[100000];
 12 bool prime[100005];
 13 LL cnt[100005];
 14 int ak[100005];
 15 int tt[200];
 16 void table(int n,int cn,int v);
 17 LL ac(int n);
 18 int main(void)
 19 {
 20         int N,Q;
 21         int i,j;
 22         for(i = 2; i < 1000; i++)
 23         {
 24                 if(!prime[i])
 25                 {
 26                         for(j = i; i*j < 100000; j++)
 27                         {
 28                                 prime[i*j] = true;
 29                         }
 30                 }
 31         }
 32         int cn = 0;
 33         for(i = 2; i < 100000; i++)
 34         {
 35                 if(!prime[i])
 36                 {
 37                         ans[cn++] = i;
 38                 }
 39         }
 40         scanf("%d %d",&N,&Q);
 41         LL sum = 0;
 42         for(i = 1; i <= N; i++)
 43         {
 44                 scanf("%d",&ak[i]);
 45                 sum += ak[i];
 46                 table(i,cn,1);
 47         }//printf("%lld
",sum);
 48         for(i = 0; i < Q; i++)
 49         {
 50                 int val;
 51                 int c;
 52                 scanf("%d",&val);
 53                 if(val == 2 )
 54                 {
 55                         scanf("%d",&c);
 56                         printf("%lld
",sum-ac(c));
 57                 }
 58                 else
 59                 {
 60                         int x,y;
 61                         scanf("%d  %d",&x,&y);
 62                         table(x,cn,0);
 63                         sum -= ak[x];
 64                         ak[x] = y;
 65                         sum += ak[x];
 66                         table(x,cn,1);
 67                 }
 68         }
 69         return 0;
 70 }
 71 void table(int n,int cn,int v)
 72 {
 73         int f = 0;
 74         bool flag = false ;
 75         int x = n;
 76         int cp = 0;
 77         while(x > 1)
 78         {
 79                 while(x%ans[f]==0)
 80                 {
 81                         if(!flag)
 82                         {
 83                                 flag = true;
 84                                 tt[cp++] = ans[f];
 85                         }
 86                         x/=ans[f];
 87                 }
 88                 f++;
 89                 flag  = false ;
 90                 if(ans[f]*ans[f]>x)
 91                         break;
 92         }
 93         if(x>1)
 94                 tt[cp++] = x;
 95         int i,j;
 96         for(i = 1; i < (1<<cp); i++)
 97         {
 98                 int sum = 1;int t = 0;
 99                 for(j = 0; j < cp; j++)
100                 {
101                         if(i&(1<< j))
102                         {
103                                 sum*=tt[j];
104                                 t++;
105                         }
106                 }
107                 if(v)
108                 {
109                         if(t%2)cnt[sum]+=ak[n];
110                         else cnt[sum]-=ak[n];
111                 }
112                 else
113                 {
114                         if(t%2)cnt[sum]-=ak[n];
115                         else cnt[sum]+=ak[n];
116                 }
117         }
118 }
119 LL ac(int n)
120 {
121         int f = 0;
122         bool flag = false ;
123         int x = n;
124         int cp = 0;
125         while(x > 1)
126         {
127                 while(x%ans[f]==0)
128                 {
129                         if(!flag)
130                         {
131                                 flag = true;
132                                 tt[cp++] = ans[f];
133                         }
134                         x/=ans[f];
135                 }
136                 f++;
137                 flag  = false ;
138                 if(ans[f]*ans[f]>x)
139                         break;
140         }
141         if(x>1)
142                 tt[cp++] = x;
143         int i,j;
144         LL k = 0;;
145         for(i = 1; i < (1<<cp); i++)
146         {
147                 int sum = 1;
148                 for(j = 0; j < cp; j++)
149                 {
150                         if(i&(1<<j))
151                         {
152                                 sum *= tt[j];
153                         }
154                 }
155                 k += cnt[sum];
156         }//printf("%lld
",k);
157         return k;
158 }

油!油!you@
原文地址:https://www.cnblogs.com/zzuli2sjy/p/5839862.html