bzoj:[SDOI2008]仪仗队
题目:https://www.luogu.org/problemnew/show/P2158
我们 考虑一下,对于每个点(x,y),设gcd(x,y) = d, 如果d != 1,则这个点一定会被(x/d,y/d)挡住,所以这题即求φ(i)
φ有两个性质
1、若p|n且, 则
2、若p|n但,则
然后就有了我们可爱的线性筛
代码:
#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;
}