数论杂题

①:给定正整数N,求满足a+b≤N,a+b|a*b,数对(a,b)的个数,N≤1e14.

我们设d = gcd(a,b).那么a = a'*d,b = b'*d,易得gcd(a',b') == 1.

将a = a'*d与b = b'*d代入a+b | a*b,易得(a'+b' ) | a'b'd.

显然我们得(a'+b') 不被 a'b'整除,那么(a' + b') | d.

我们设a' + b' = k, k * d = n ,t*k = d,那么k ∈[ 2,sqrt(N)].

那对于一个给定的k,它的合法个数呢?

(a'+b')*d = k * k * t ≤ n,那么t  ≤ N/(k*k),注意k是不变的,t 的范围即k在N范围内的合法个数.

那对于一个给定k,合法(a',b')数对的个数呢?应为k = a'+b',gcd(a'+b',a') = 1,那么ans显然是φ(k).

ans = (n/k*k)*φ(k),k∈[2.sqrt(N)],O(sqrt(N))

 

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
#define e exit(0)
#define re register
#define LL long long
const LL maxn = 1e7+1;
LL n,t,ans;
int cnt,prime[maxn],vis[maxn],Ins[maxn];
int main()
{
    scanf("%lld",&n);
    LL t = sqrt(n);
    Ins[1] = 1;
    for(re int i=2;i<=t;++i){    
        if(!vis[i]){
            prime[++cnt] = i;
            Ins[i] = i-1;
        }
        for(re int j=1;j<=cnt;++j){
            if(i*prime[j] > t)
                break;
            vis[i*prime[j]] = 1;
            if(i%prime[j] == 0){
                Ins[i*prime[j]] = Ins[i]*prime[j];
                break;
            }
            else Ins[i*prime[j]] = Ins[i]*Ins[prime[j]];
        }
    }
    for(re LL k=2;k<=t;++k)
        ans += (LL)(n/(k*k))*(LL)Ins[k];
    printf("%lld",ans);
    return 0;
}

 

 

猜你喜欢

转载自www.cnblogs.com/xqysckt/p/11809290.html