神炎皇乌利亚很喜欢数对,他想找到神奇的数对。
对于一个整数对(a,b),若满足a+b<=n且a+b是ab的因子,则成为神奇的数对。请问这样的数对共有多少呢?
一行一个整数表示答案,保证不超过64位整数范围。
对于20%的数据n<=1000;
对于40%的数据n<=100000;
对于60%的数据n<=10000000;
对于80%的数据n<=1000000000000;
对于100%的数据n<=100000000000000。
很明显,20分的暴力是肯定有的,但是,正解怎么来呢?
得到正解需要证明两个前置性质:
设d=gcd(a,b);
->a1=a/d b1=b/d;
第一个:
因为a1,b1互质
-> gcd(a1,b1)==1
-> gcd(a1+b1,a1)==1 gcd(a1+b1,b1)==1
-> gcd(a1+b1,a1*b1)==1
第二个:
当ab是a+b的倍数时。
a+b|ab
-> d(a1+b1)|d^2*a1*b1
-> a1+b1|d*a1*b1
因为gcd(a1+b1,a1*b1)==1
-> d=k(a1+b1);
现在我们在转到题目上来:
a+b<=n
-> d(a1+b1)<=n
-> k(a1+b1)^2<=n
-> k<=n/(a1+b1)^2
我们枚举(a1+b1),只有sqrt(n)的复杂度,因为k肯定是正整数。
假设我们现在枚举到了(a1+b1)==x,
那么在n的范围内的a+b有n/x^2个(k有这么多个)
而每个a+b有可以对应不同的ab,这里的ab数目正好是(a1+b1)的欧拉函数(相信可以理解的);
最终,我们的答案就是:
for(int i=1;i<=sqrt(n);i++)
{
ans+=phi[i]*n/i/i;
}
代码:
∑n√i=1φ(i)∗ni
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define ll long long
#define il inline
#define db double
using namespace std;
ll prime[10000045],cnt;
ll phi[10000045];
bool vis[10000045];
il void init()
{
for(int i=2;i<=10000000;i++)
{
if(!vis[i])
{
prime[++cnt]=i;
phi[i]=i-1;
}
for(int j=1;j<=cnt;j++)
{
if(prime[j]*i>10000000)
break;
vis[prime[j]*i]=1;
if(i%prime[j]==0)
{
phi[prime[j]*i]=phi[i]*prime[j];
break;
}
else
phi[prime[j]*i]=phi[i]*(prime[j]-1);
}
}
}
int main()
{
init();//xian xing shai qiu phi
ll n;
cin>>n;
int p=sqrt(n);
ll ans=0;
for(int i=1;i<=p;i++)
ans+=phi[i]*n/i/i;//suan chu lai de
printf("%lld\n",ans);
return 0;
}
daia