您的位置:首页 > 其它

BZOJ2671 : Calc

2015-08-31 12:07 351 查看
设$d=\gcd(a,b),a=xd,b=yd$,则$a+b|ab$等价于$x+y|xyd$。

因为$x,y$互质,所以$x+y|d$。

假设$x<y$,那么对于固定的$x,y$,有$\lfloor\frac{n}{y(x+y)}\rfloor$个$d$。

枚举$y$,设$m=\lfloor\frac{n}{y}\rfloor$,则它的贡献为:

\[\begin{eqnarray*}
&&\sum_{i=1}^{y-1}[\gcd(i,y)=1]\lfloor\frac{m}{i+y}\rfloor\\
&=&\sum_{i=1}^{y-1}\sum_{d|\gcd(i,y)}\mu(d)\lfloor\frac{m}{i+y}\rfloor\\
&=&\sum_{i=1}^{y-1}\sum_{d|i,d|y}\mu(d)\lfloor\frac{m}{i+y}\rfloor\\
&=&\sum_{d|y}\mu(d)\sum_{d|i}\lfloor\frac{m}{i+y}\rfloor
\end{eqnarray*}\]

枚举$y$的约数$d$,再分段计算$\sum_{d|i}\lfloor\frac{m}{i+y}\rfloor$即可。

时间复杂度$O(N^\frac{3}{4}\log N)$。

#include<cstdio>
typedef long long ll;
const int N=46500,M=505030;
int n,m,lim,i,j,d,l,r,vis
,tot,p
,mu
,g
,v[M],nxt[M],ed;ll ans,t;
inline void add(int x,int y){v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
int main(){
for(scanf("%d",&n);(ll)lim*(lim+1)<=n;lim++);
for(mu[1]=1,i=2;i<lim;i++){
if(!vis[i])p[tot++]=i,mu[i]=-1;
for(j=0;j<tot;j++){
if(i*p[j]>=lim)break;
vis[i*p[j]]=1;
if(i%p[j])mu[i*p[j]]=-mu[i];else break;
}
}
for(i=1;i<lim;i++)if(mu[i])for(j=i;j<lim;j+=i)add(j,i);
for(i=2;i<lim;i++)for(m=n/i,j=g[i];j;j=nxt[j]){
for(t=0,d=v[j],l=1;l<i&&i+l<=m;l=r+1){
r=m/(m/(i+l))-i;
if(r>=i)r=i-1;
t+=(ll)(r/d-(l-1)/d)*(m/(i+l));
}
ans+=t*mu[d];
}
return printf("%lld",ans),0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: