P2158 [SDOI2008]仪仗队(欧拉函数求范围内互质的数)
作为体育委员,C君负责这次运动会仪仗队的训练。仪仗队是由学生组成的N * N的方阵,为了保证队伍在行进中整齐划一,C君会跟在仪仗队的左后方,根据其视线所及的学生人数来判断队伍是否整齐(如下图)。
现在,C君希望你告诉他队伍整齐时能看到的学生人数。
思路:观察图形,所有能看到到的点都是直线,一条直线代表一个点,而直线的斜率都不相等,也就是k=y/x的总数,要k不同,y与x互质时的k就是唯一的,
所以我们可以想到,在x=2-n时,所有小于x且与它互质的数就是它们能组合出的斜率个数,也就是欧拉函数,然后把数的欧拉函数值求和即可
AC代码:
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 40005; int e[maxn]; int main() { //freopen("test.txt", "r", stdin); int n; scanf("%d", &n); if (n == 1) { printf("0\n"); return 0; } n--; for (int i = 1; i <= n; i++) { e[i] = i; } for (int i = 2; i <= n; i++) {//欧拉函数求法,配合筛法 if (e[i] == i) {//是质数 for (int j = i; j <= n; j += i) { e[j] = e[j] / i * (i - 1); } } } int ans = 1; for (int i = 1; i <= n; i++) { ans += e[i] * 2; } cout << ans << endl; return 0; }
线性筛模板
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 200005; const int N = 10000005; bool is_prime[N]; int n, prime_num, prime[N], phi[N]; long long sum[N]; int main() { scanf("%d", &n); memset(is_prime, 1, sizeof(is_prime)); is_prime[1] = 0; phi[1] = 1; for (int i = 2; i <= n; ++i) { if (is_prime[i]) phi[i] = i - 1, prime[++prime_num] = i; for (int j = 1; j <= prime_num && prime[j] * i <= n; ++j) { is_prime[prime[j] * i] = 0; if (i % prime[j] == 0){ phi[prime[j] * i] = prime[j] * phi[i]; break; } else { phi[prime[j] * i] = phi[prime[j]] * phi[i]; } } } for (int i = 1; i <= n; ++i) sum[i] = sum[i - 1] + phi[i]; long long ans = 0; for (int i = 1; i <= prime_num && prime[i] <= n; ++i) ans += (sum[n / prime[i]] << 1) - 1; printf("%lld\n", ans); return 0; }