题目大意
有这样一个分数等式:1/X + 1/Y = 1/N,(X,Y,N > 0)。给出L,求有多少满足X < Y <= L的等式。
例如:L = 12,满足条件的等式有3个,分别是:1/3 + 1/6 = 1/2, 1/4 + 1/12 = 1/3, 1/6 + 1/12 = 1/4。
数论题
大师张俊不教我我不会。。
其实就是求多少对(a,b)满足a+b|ab
设d=(a,b),a1*d=a,b1*d=b
d∗(a1+b1)|d2∗a1∗b1
a1+b1|d∗a1∗b1
因为(a1,b1)=1,那么我们其实只需要满足
a1+b1|d
∑na=1∑nb=a+1[(a,b)=1]∗(n/b)/(a+b)
我们莫比乌斯反演一波
∑nd=1μ(d)∗∑n/da=1∑n/db=a+1(n/d2/b)/(a+b)
∑√nd=1∑√n/db=1∑b−1a=1(n/d2/b)/(a+b)
枚举前两个最后一个分块,复杂度不会算。
#include<cstdio>
#include<algorithm>
#include<cmath>
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
typedef long long ll;
const int maxn=320000+10;
int mu[maxn],pri[maxn];
bool bz[maxn];
int i,j,k,l,t,m,top,a,b,d;
ll ans,n;
void calc(int b,int d){
int i=1,j;
ll k;
while (i<=b-1){
k=(n/((ll)d*d)/(ll)b)/(ll)(i+b);
if (!k) break;
j=(n/((ll)d*d)/(ll)b)/k-(ll)b;
j=min(j,b-1);
ans+=(ll)mu[d]*(j-i+1)*((n/((ll)d*d)/(ll)b)/(ll)(i+b));
i=j+1;
}
}
int main(){
mu[1]=1;
fo(i,2,maxn-10){
if (!bz[i]){
pri[++top]=i;
mu[i]=-1;
}
fo(j,1,top){
if ((ll)i*pri[j]>maxn-10) break;
bz[i*pri[j]]=1;
if (i%pri[j]==0){
mu[i*pri[j]]=0;
break;
}
mu[i*pri[j]]=-mu[i];
}
}
scanf("%lld",&n);
m=floor(sqrt(n));
fo(d,1,m){
if (mu[d]==0) continue;
fo(b,1,m/d) calc(b,d);
}
printf("%lld\n",ans);
}