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;
}

 

 
posted @ 2021-03-26 14:50  cono奇犽哒  阅读(65)  评论(0)    收藏  举报