浏览器标题切换
浏览器标题切换end
把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

BZOJ2818: Gcd 欧拉函数

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

Solution

看着黄学长的题解才弄懂这道题的QAQ,我数论真的好差啊...

求$gcd(x,y)=p$,p为素数的x,y取值有多少种

每个素数p对答案的贡献是$1$~$n/p$的有序互质对个数

我们可以设$y>=x$,显然当$x$确定的时候这个素数$p$的贡献就是$\phi(y)$

所以有序质数对的个数为$\sum_{i=1}^{i<=n/p}{\phi(i)}*2-1$

(有序质数对所以乘2,然后(1,1)在这里被算了2次所以-1)

#include <bits/stdc++.h>

using namespace std ;

#define ll long long
const int N = 1e7+10 ;

int n , tot ;
int phi[ N ] , p[ N ] ;
ll c[ N ] , ans ;
bool v[ N ] ;

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

int main() {
    scanf( "%d" , &n ) ;
    eular() ;
    for( int i = 1 ; i <= n ; i ++ ) 
        c[ i ] = c[ i - 1 ] + phi[ i ] ;
    for( int i = 1 ; i <= tot ; i ++ ) {
        ans += c[ n / p[ i ] ] * 2 - 1 ;
    }
    printf( "%lld\n" , ans ) ;
} 

 

posted @ 2018-10-26 21:59  henry_y  阅读(171)  评论(0编辑  收藏  举报