bzoj2818: Gcd

2818: Gcd

Time Limit: 10 Sec  Memory Limit: 256 MB

Description

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

 

Input

一个整数N

Output

如题

Sample Input

4

Sample Output

4

HINT

 

hint

对于样例(2,2),(2,4),(3,3),(4,2)


1<=N<=10^7

题解:gcd(x, y) = p   <==> gcd(x/p, y/p) = 1   <==> phi[y/p] if(x/p is smaller)   p is a prime

我们就枚举p好了, x中有x/p个满足为p 的倍数,我们就需要Σ(i < x/p) phi[i] 的前缀和,然后答案*2 -1(*2是交换x和y, -1是因为phi[1]是x == y, 我们这里phi[1] = 1)

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int M = 1e7 + 10;
bool vis[M];
int cnt;
int p, phi[M], prime[M];
ll sum[M];
void init(int t){
    phi[1] = 1;
  
    for(int i = 2; i <= t; i++){
        if(!vis[i]) phi[i] = i-1, prime[++cnt] = i;
        for(int j = 1; j <= cnt && i * prime[j] <= t; j++){
            int m = i * prime[j]; vis[m] = 1;
            if(i % prime[j] == 0) {
                phi[m] = phi[i] * prime[j];
                break;
            }
            phi[m] = phi[i] * (prime[j] - 1);
        }
    }
     
    for(int i = 1; i <= t; i++) sum[i] = sum[i-1] + phi[i]*1LL;
}
  
int main(){
    int t;
    ll ans = 0;
    scanf("%d", &t);
    init(t);
    for(int i = 1; i <= cnt; i++)
        ans += 2*sum[t/prime[i]] - 1;//, cout<<sum[t/prime[i]]<<endl;
    printf("%lld", ans);
}
View Code

 

 

转载于:https://www.cnblogs.com/EdSheeran/p/9329517.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值