1. 程式人生 > >神炎皇 數學

神炎皇 數學

borde ble flow namespace 1.7 bsp position adding ram

神炎皇烏利亞很喜歡數對,他想找到神奇的數對。
對於一個整數對(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\n",ans);

	return 0;
}

daia

神炎皇 數學