bzoj:[SDOI2008]仪仗队

题目:https://www.luogu.org/problemnew/show/P2158

我们 考虑一下,对于每个点(x,y),设gcd(x,y) = d, 如果d != 1,则这个点一定会被(x/d,y/d)挡住,所以这题即求\sumφ(i)

φ有两个性质

1、若p|n且p^2|n, 则\phi(n) = \phi(n/p)*p

2、若p|n但p^2\nmid n,则\phi(n) =\phi(n/p) * (p - 1)

然后就有了我们可爱的线性筛

代码:

#include<bits/stdc++.h>
#define N 1000005
using namespace std;
int prime[N], vis[N], phi[N], sz, n, ans;
void get_phi(){
	for(int i = 2; i < N; i ++){
		if(!vis[i]){
			prime[++ sz] = i;
			phi[i] = i - 1;//显而易见
		}
		for(int j = 1; prime[j] * i < N; j ++){
			vis[i * prime[j]] = 1;
			if(i % prime[j] == 0){
				phi[i * prime[j]] = phi[i] * prime[j]; //性质1
				break;
			}
			phi[i * prime[j]] = phi[i] * (prime[j] - 1);//性质2
		}
	}
}
int main(){
	get_phi();
	scanf("%d", &n);
	if(n == 1) {printf("0");return 0;}
	for(int i = 2; i < n; i ++) ans += phi[i];
	printf("%d", 3 + ans * 2);
	return 0;
}

 

posted @ 2018-10-30 20:04  lahlah  阅读(17)  评论(0编辑  收藏  举报