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