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