Description
神炎皇乌利亚很喜欢数对,他想找到神奇的数对。
对于一个整数对(a,b),若满足a+b<=n且a+b是ab的因子,则成为神奇的数对。请问这样的数对共有多少呢?
Input
一行一个整数n。
Output
一行一个整数表示答案,保证不超过64位整数范围。
Sample Input
21
Sample Output
11
Data Constraint
对于20%的数据n<=1000;
对于40%的数据n<=100000;
对于60%的数据n<=10000000;
对于80%的数据n<=1000000000000;
对于100%的数据n<=100000000000000。
好久没打,偷个懒。
解法
首先如果
a+b|ab
成立。
我们设
gcd(a,b)=k
,则有
a′k=a,b′k=b
.
得到
k(a′+b′)|a′b′d2
即
a′+b′|a′b′k。
因为
gcd(a′,b′)=1
所以
a′+b′|k
题目有
(a′+b′)k<=n.
那么最大情况下
a′+b′<=n√
。
k就有
ni2
种情况。
因为
gcd(a',b')=gcd(a'+b',a')
所以a′和b′又有
φ(i)
种
线性筛出phi即可。
时间
O(n√)
;
代码
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
#define fo(i,a,b) for(ll i=a;i<=b;i++)
#define ll long long
using namespace std;
const ll maxn=1e7+5;
ll n,phi[maxn],pri[maxn],tot,ans;
bool bz[maxn];
int main()
{
freopen("uria.in","r",stdin);
freopen("uria.out","w",stdout);
scanf("%lld",&n);
tot=sqrt(n);
fo(i,2,tot){
if (!bz[i]) {
pri[++pri[0]]=i;
phi[i]=i-1;
}
fo(j,1,pri[0]){
if (i*pri[j]>tot) break;
bz[i*pri[j]]=1;
if(i%pri[j]==0){
phi[i*pri[j]]=phi[i]*pri[j];
break;
}
else phi[i*pri[j]]=phi[i]*(pri[j]-1);
}
}
fo(i,1,tot){
ll now=n/(i*i);
ans+=now*phi[i];
}
printf("%lld\n",ans);
}