题目描述
神炎皇乌利亚很喜欢数对,他想找到神奇的数对。
对于一个整数对(a,b),若满足a+b<=n且a+b是ab的因子,则成为神奇的数对。请问这样的数对共有多少呢?
数据范围
对于100%的数据n<=100000000000000。
=w=
引理一
两个互质的数之差与这两个数互质。
证明:
证明依赖于欧几里得算法的
gcd(a,b)=gcd(b,a−b)
。
1.设
a>b,r=(a,b)
,则有
r|a,r|b
,表示成
a=a′∗r,b=b′∗r
。
则有
(b,a−b)=(b′∗r,(a′−b′)∗r)
,显然
(b,a−b)
也有
r
这个公约数。
2.设
则有
(a+b,a)=((a′+b′)∗r,a′∗r)
,显然
(a+b,a)
也有
r
这个公约数。
综合1,2,
回到原命题,
gcd(p,q)=1⇒gcd(q,p−q)=1
。
引理二
两个互质的数的和与积互质。
证明:
设
gcd(p,q)=1
,
根据引理一,则有
gcd(p+q,q)=gcd(q,p)=1,gcd(p+q,p)=gcd(p,q)=1
也就是说
(p+q)
与
p
和
正文
若
(a,b)
合法,那么存在
(a+b)|ab
设
d=gcd(a,b)
,并且
a′∗d=a,b′∗d=b
。
那么就有
(a′+b′)d|a′b′d2
,即
(a′+b′)|a′b′d
。
根据引理二,又
a′
与
b′
互质,则
(a′+b′)|d
。
题设有
a+b<=n
,那么
(a′+b′)d<=n
。
由
(a′+b′)|d
,
d
至少为
又
(a′+b′)d<=n
,那么
(a′+b′)<=n√
。
不妨枚举
i=(a′+b′)
,这样
d
就只能取
所以合法的
d
就有
再来考虑符合
(a′+b′)=i
的个数,由引理一:
如果存在一个
gcd(c,i)=1
,那么必然存在一个
gcd(c,i−c)=1
。
于是乎,
(a′+b′)=i
的个数即为
φ(i)
,可用线性筛法预处理。
综上,
ans=∑n√i=2ni2∗φ(i)
。
时间复杂度为
O(n√)
。
代码
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define ll long long
using namespace std;
const char* fin="uria.in";
const char* fout="uria.out";
const int inf=0x7fffffff;
const int maxn=10000007;
ll n,i,j,k,nq;
ll ans;
ll p[maxn],phi[maxn];
bool bz[maxn];
int main(){
freopen(fin,"r",stdin);
freopen(fout,"w",stdout);
scanf("%lld",&n);
nq=(ll)sqrt(n);
for (i=2;i<=nq;i++){
if (bz[i]==false){
phi[i]=i-1;
p[++p[0]]=i;
ans+=phi[i]*(n/i/i);
}
for (j=1;j<=p[0];j++){
k=i*p[j];
if (k>nq) break ;
if (i%p[j]==0) phi[k]=phi[i]*p[j];
else phi[k]=phi[i]*(p[j]-1);
bz[k]=true;
ans+=phi[k]*(n/k/k);
if (i%p[j]==0) break;
}
}
printf("%lld\n",ans);
return 0;
}
=o=
线性筛法求欧拉函数
首先有通式,
φ(p1k1∗p2k2∗...∗pnkn)=(p1−1)∗p1k1−1∗(p2−1)∗p2k2−1∗...∗(pn−1)∗pnkn−1
。
显然用线筛通过简单转移可以得到。
~
一开始我也考虑分析这个东西,
(a,b)
合法就有
(a′+b′)|a′b′d
。
然后就不会了。
并没有考虑到
gcd(a′+b′,a′b′)=1
这个性质。
日后这种数论计数问题,先从合法的开始分析。
如果涉及倍数关系,可以考虑排除一些不作贡献的干扰项。