数论杂题
①:给定正整数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; }