Description
神炎皇乌利亚很喜欢数对,他想找到神奇的数对。
对于一个整数对
(a,b)
,若满足
a+b<=n
且
a+b
是
ab
的因子,则成为神奇的数对。请问这样的数对共有多少呢?
Input
一行一个整数n。
Output
一行一个整数表示答案,保证不超过64位整数范围。
Sample Input
21
Sample Output
11
Data Constraint
对于20%的数据
n<=103
;
对于40%的数据
n<=105
;
对于60%的数据
n<=106
;
对于80%的数据
n<=1012
;
对于100%的数据
n<=1014
。
Solution
观察 a+b<=n 且 a+b|ab
使
d=Gcd(a,b)必然 d>1 才能使 a+b|ab则
a=a′d,b=b′d可知
Gcd(a′,b′)=1推出
Gcd(a′+b′,b′)=1所以
a+b|ab=>(a′+b′)d|a′b′d2=>a′+b′|a′b′d因为
a′+b′∤a′b′所以
a′+b′|d又设
d=c(a′+b′)则
a+b=d(a′+b′)=(a′+b′)2⋅p≤n且p>0所以
a′+b′≤n√设
k=a′+b′,之后枚举 k 。由于p可能的取值为
⌊nk2⌋ 由
Gcd(a′+b′,b′)=1得Gcd(k,b′)=1那么b’的取值就是
φ(k)所以答案就是
∑k=1n√k∗⌊nk2⌋∗φ(k)因为 φ(k) 可以用线性筛法求出!
最终时间复杂度就是
O(n√)
Code
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long LL;
const int N=10000001;
int m;
LL n,ans;
int f[N],phi[N];
bool bz[N];
int main()
{
scanf("%lld",&n);
m=sqrt(n);
for(int i=2;i<=m;i++)
{
if(!bz[i]) phi[f[++f[0]]=i]=i-1;
for(int j=1;j<=f[0] && i*f[j]<=m;j++)
{
bz[i*f[j]]=true;
if(i%f[j]==0)
{
phi[i*f[j]]=phi[i]*f[j];
break;
}else phi[i*f[j]]=phi[i]*(f[j]-1);
}
}//线性筛法
for(int i=2;i<=m;i++) ans+=n/(1LL*i*i)*1LL*phi[i];
printf("%lld",ans);
return 0;
}