GENEVE

我还想继续玩c++

导航

BZOJ2818

Posted on 2015-09-28 11:26  GENEVE  阅读(162)  评论(0编辑  收藏  举报

好久没有更新啦,今天上午就这一题卡了半天,然而只是一些小问题影响时间

这题目没法再简述了,题目描述很清晰

给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的
数对(x,y)有多少对.

我们来看一下性质: gcd(x,y) = z, 那么gcd(x/z,y/z) = 1,这个是显然的,那我们不妨假设y >= x 那么答案基本也是显然的了

剩下的就是求欧拉函数了,枚举z即可,用前缀和记录即可(不要树状数组,粗暴记录就行了)

 

说说今天蹦的地方吧:先是Size开小了,然后是数组类型小了(前缀和会爆int),接着全改成long long后会mle,浪费了接近半小时,这提醒我们一定要注意数组的类型啊

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>

using namespace std;

typedef long long ll;

const int Size = 1e7 + 7;

int n; 
int prime[Size],phi[Size],factor_max[Size];
ll sum[Size];
ll ans;

void Euler(void);

int main(){
    scanf("%d",&n);
    Euler();
    for(int i = 1;i <= n; ++i)
        sum[i] = sum[i - 1] + phi[i];
    for(int i = 1;i <= prime[0]; ++i)
        ans += sum[n / prime[i]] * 2 - 1;
    printf("%lld",ans);
    return 0;
}

void Euler(void){
    phi[1] = 1;
    for (int i = 2;i <= n; ++i){
        if (!factor_max[i]){
            factor_max[i] = i;
            prime[++prime[0]] = i;
            phi[i] = i-1; 
        }
        for (int j = 1;j <= prime[0]; ++j){
            if (prime[j] * i > n)    break;
            if (i % prime[j] != 0)
                    phi[i * prime[j]] = phi[i] * (prime[j] - 1);
            else    phi[i * prime[j]] = phi[i] * prime[j];
            factor_max[i * prime[j]] = prime[j];
            if (i % prime[j] == 0)    break; 
        }
    }
}