神炎皇 数学

神炎皇乌利亚很喜欢数对,他想找到神奇的数对。
对于一个整数对(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;

}

代码:

ni=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
",ans);

	return 0;
}

daia

原文地址:https://www.cnblogs.com/gshdyjz/p/7678533.html