神炎皇
(File IO): input:uria.in output:uria.out
Time Limits: 1000 ms Memory Limits: 524288 KB
Description
神炎皇乌利亚很喜欢数对,他想找到神奇的数对。
对于一个整数对(a,b),若满足a+b<=n且a+b是ab的因子,则成为神奇的数对。请问这样的数对共有多少呢?
Input
一行一个整数n。
Output
一行一个整数表示答案,保证不超过64位整数范围。
Sample Input
21
Sample Output
11
Data Constraint
对于20%的数据n<=10^3;
对于40%的数据n<=10^5;
对于60%的数据n<=10^7;
对于80%的数据n<=10^12;
对于100%的数据n<=10^14。
解题思路
假设 gcd(a,b)=d ,必然有d>1才能使 a+b|ab ,这时,我们设 a=a′d,b=b′d ,必有 gcd(a′,b′)=1,a′+b′∤a′b′,gcd(a′+b′,a′)=1 ,a+b|ab化为
再设 i(a′+b′)=d 则 a+b=d(a′+b′)=(a′+b′)2i≤n i>0,则 a′+b′≤n√
设 k=a′+b′ ,枚举k,则i可能取的值的个数是 ⌊nk2⌋ 个 gcd(k,a′) 则a’的取值个数是 φ(k) 所以答案就是
其中 φ(k) 可以用线性筛法求
或者是,若
那么 φ(k)=φ(kp)∗p(p|k)或φ(k)=φ(kp)∗(p−1)(p∤k) 这样就可以用线性筛法套上去求φ(k)了
O(n√)
Codes
#include<cstring>
#include<cstdio>
using namespace std;
long long n,ans,f[10000100],pr[10000100];
int main()
{
for(int i=2;i<=10000000;i++)f[i]=i-1;
for(int i=2;i<=10000000;i++)
{
if(f[i]==i-1)
{
pr[++pr[0]]=i;
}
for(int j=1;j<=pr[0];j++)
{
if(pr[j]*i>10000000)break;
if(i%pr[j]==0)
{
f[i*pr[j]]=f[i]*pr[j];
break;
}else
{
f[i*pr[j]]=f[i]*(pr[j]-1);
}
}
}
freopen("uria.in","r",stdin);
freopen("uria.out","w",stdout);
scanf("%lld",&n);
for(long long i=2;i*i<=n;i++)
{
ans+=n/(i*i)*f[i];
}
printf("%lld",ans);
}
扩展
另外还有一些关于φ(k)的公式:
1.
2.