Sum
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2974 Accepted Submission(s): 843
Problem Description
XXX is puzzled with the question below:
1, 2, 3, ..., n (1<=n<=400000) are placed in a line. There are m (1<=m<=1000) operations of two kinds.
Operation
1: among the x-th number to the y-th number (inclusive), get the sum of
the numbers which are co-prime with p( 1 <=p <= 400000).
Operation 2: change the x-th number to c( 1 <=c <= 400000).
For each operation, XXX will spend a lot of time to treat it. So he wants to ask you to help him.
Input
There are several test cases.
The first line in the input is an integer indicating the number of test cases.
For each case, the first line begins with two integers --- the above mentioned n and m.
Each the following m lines contains an operation.
Operation 1 is in this format: "1 x y p".
Operation 2 is in this format: "2 x c".
Output
For each operation 1, output a single integer in one line representing the result.
Sample Input
1
3 3
2 2 3
1 1 3 4
1 2 3 6
Sample Output
7
0
思路:容斥原理;
因为原数列是[1,n];所以数的和我们可以直接用求和公式;
然后m<1000;所以改变的最多不超过1000;我们用数组存改变,改变的位置会重复,这时后要覆盖,也就是数组中原先已有这个点,我们可以用map标记是否在数组中已有;
没有的话加入,有的话覆盖。
然后询问是[x,y]区间内与z互质的数的和,所以我们考虑分解z,那么素数打表。
然后容斥求在[x,y]与z互质数的和;然后再循环一遍改变,判断替换的数,和原来的数是否与z互质,原来的数互质的话减去原来的,改变的数互质的话,加上改变的数;
每个数的不同的质因数不超过9个;
复杂度(5120*m);
1 #include<stdio.h> 2 #include<algorithm> 3 #include<iostream> 4 #include<stdlib.h> 5 #include<string.h> 6 #include<queue> 7 #include<map> 8 typedef long long LL; 9 using namespace std; 10 bool prime[400005]; 11 int ans[400005]; 12 queue<int>que; 13 int cm[400005]; 14 int ma[400005]; 15 int flag[2000]; 16 int gcd(int n,int m); 17 map<int,int>my; 18 int main(void) 19 { 20 int i,j,k; 21 int p,q; 22 int n,m; 23 int x,y; 24 int t; 25 for(i=2; i<=2000; i++) 26 { 27 if(!prime[i]) 28 { 29 for(j=i; i*j<=400000; j++) 30 { 31 prime[i*j]=true; 32 } 33 } 34 } 35 int cnt=0; 36 for(i=2; i<=400000; i++) 37 { 38 if(!prime[i]) 39 { 40 ans[cnt++]=i; 41 } 42 } 43 scanf("%d",&k); 44 while(k--) 45 { my.clear(); 46 scanf("%d %d",&p,&q); 47 int bt=1; 48 for(i=0; i<=p; i++) 49 ma[i]=i; 50 while(q--) 51 { 52 scanf("%d",&n); 53 if(n==1) 54 { 55 scanf("%d %d %d",&x,&y,&t); 56 int r=0; 57 int yy=0; 58 int xy=t; 59 if(x>y)swap(x,y); 60 while(t>1) 61 { 62 if(r==0&&t%ans[yy]==0) 63 { 64 r=1; 65 que.push(ans[yy]); 66 t/=ans[yy]; 67 } 68 else if(r==1&&t%ans[yy]==0) 69 { 70 t/=ans[yy]; 71 } 72 else 73 { 74 r=0; 75 yy++; 76 } 77 } 78 x-=1; 79 int ak=0; 80 while(!que.empty()) 81 { 82 cm[ak++]=que.front(); 83 que.pop(); 84 } 85 LL sum1=0; 86 LL sum2=0; 87 for(i=1; i<=(1<<ak)-1; i++) 88 { 89 int nn=0; 90 LL dp=1; 91 for(j=0; j<ak; j++) 92 { 93 if(i&(1<<j)) 94 { 95 nn++; 96 dp*=(LL)cm[j]; 97 } 98 } 99 if(nn%2) 100 { 101 LL ct=y/dp; 102 LL qt=x/dp; 103 LL ct1=ct+1; 104 LL qt1=qt+1; 105 sum1+=dp*ct1*ct/2; 106 sum2+=dp*qt1*qt/2; 107 } 108 else 109 { 110 LL ct=y/dp; 111 LL qt=x/dp; 112 LL ct1=ct+1; 113 LL qt1=qt+1; 114 sum1-=dp*ct1*ct/2; 115 sum2-=dp*qt1*qt/2; 116 } 117 } LL xc=1+x;LL yc=1+y; 118 LL ap1=(long long )(xc)*(long long)x/2; 119 LL ap2=(long long)(yc)*(long long)y/2; 120 ap2-=sum1; 121 ap1-=sum2; 122 ap2-=ap1; 123 for(j=1; j<bt; j++) 124 { 125 if(flag[j]>=x+1&&flag[j]<=y) 126 { 127 int cp=gcd(xy,ma[flag[j]]); 128 int cq=gcd(xy,flag[j]); 129 if(cq==1) 130 ap2-=flag[j]; 131 if(cp==1) 132 ap2+=ma[flag[j]]; 133 } 134 } 135 printf("%lld\n",ap2); 136 } 137 else 138 { 139 scanf("%d %d",&x,&t); 140 if(my[x]==0) 141 {my[x]=1;flag[bt]=x;bt++;} 142 ma[x]=t; 143 } 144 } 145 } 146 return 0; 147 } 148 int gcd(int n,int m) 149 { 150 if(m==0) 151 return n; 152 else if(n%m==0) 153 return m; 154 else return gcd(m,n%m); 155 }