LOJ6052 DIV

LOJ6052 DIV

题面:LOJ

解析

题中所给条件即为:

\[ac-bd=k \]

\[ad+bc=0 \]

那么,不妨设 \(b \gt 0\)\(\frac{a}{b}=-\frac{c}{d}=\frac{p}{q}\),其中:\((p,q)=1\)

那么有:\(ac-bd=p^2\frac{ac}{p^2}-q^2\frac{bd}{q^2}=p^2\frac{ac}{p^2}+q^2\frac{ac}{p^2}=\frac{ac}{p^2}(p^2+q^2)=xy(p^2+q^2)=k\),其中:\(x=\frac{a}{p}\)\(y=\frac{c}{p}\)

那么\(b>0\)部分的答案即为:

\[=\sum_{i=1}^{n}\sum_{p^2+q^2|i,(p,q)=1}p\sum_{x|\frac{i}{p^2+q^2}}x \]

\[=\sum_{i=1}^{n}\sum_{p^2+q^2|i,(p,q)=1}p\times\sigma(\frac{i}{p^2+q^2}) \]

\[=\sum_{i=1}^{n}\sigma(i)\sum_{p^2+q^2\leq\lfloor\frac{n}{i}\rfloor}p[(p,q)=1] \]

\[=\sum_{i=1}^{n}\sigma(i)\sum_{p^2+q^2\leq\lfloor\frac{n}{i}\rfloor}p\sum_{d|p,d|q}\mu(d) \]

\[=\sum_{d=1}^{\lfloor\sqrt{n}\rfloor}i\mu(i)F(\frac{n}{i^2}) \]

其中:\(F(n)=\sum_{i=1}^{n}\sigma(i)\sum_{p^2+q^2\leq\lfloor\frac{n}{i}\rfloor}p\)

考虑计算\(F(n)\),对\(\lfloor\frac{n}{i}\rfloor\)数论分块,有\(\sum_{i=1}^{n} \sigma(i)=\sum_{i=1}^{n}i\lfloor\frac{n}{i}\rfloor\)
又有\(G(n)=\sum_{p^2+q^2\leq n}p=\sum_{i=1}^{\lfloor\sqrt{n}\rfloor}i\lfloor\sqrt{k-p^2}\rfloor\)

类似于杜教筛,预处理加记忆化以后复杂度为\(O(n^{\frac{2}{3}})\)

\(b<0\)的部分与\(b>0\)的部分对称,答案乘\(2\)即可。

对于\(b=0\),加上:\(\sum_{ac\leq n}a=\sum_{i=1}^{n}\sigma(i)=\sum_{i=1}^{n}i\lfloor\frac{n}{i}\rfloor\)即可。

代码


#include <cmath>
#include <cstdio>

typedef long long ll;

const int mod=1004535809;

const int inv2=502267905;

const int N=4e6+5;

ll n,m,no_pri[N],pri[N],pri_cnt,mu[N],minp[N],sigma[N],sum[N],ans;

void sieve(int n){
	for(int i=1;i*i<=n;++i){
		sum[i*i]=(sum[i*i]+i)%mod;
		for(int j=1;i*i+j*j<=n;++j) sum[i*i+j*j]=(sum[i*i+j*j]+2*i)%mod;
	}
	no_pri[1]=mu[1]=minp[1]=sigma[1]=1;
	for(int i=2;i<=n;++i){
		if(!no_pri[i]){
			pri[++pri_cnt]=i; mu[i]=-1; minp[i]=i; sigma[i]=i+1;
			for(ll j=i;j*i<=n;j*=i) sigma[j*i]=sigma[j]*i+1;
		}
		for(int j=1;pri[j]*i<=n;++j){
			no_pri[i*pri[j]]=1;
			if(i%pri[j]==0){
				minp[i*pri[j]]=minp[i]*pri[j];
				sigma[i*pri[j]]=sigma[i/minp[i]]*(sigma[minp[i]]*pri[j]+1);
				break;
			}
			mu[i*pri[j]]=-mu[i];
			minp[i*pri[j]]=pri[j];
			sigma[i*pri[j]]=sigma[i]*(pri[j]+1);
		}
	}
	for(int i=1;i<=n;++i) sum[i]=(sum[i-1]+sum[i])%mod;
	for(int i=1;i<=n;++i) sigma[i]=(sigma[i-1]+sigma[i])%mod;
}

ll Sqrt(ll n){
	ll x=sqrt(n); if(x*x<=n) ++x; if(x*x>n) --x; return x;
}

struct Array{
	ll a[100005],b[100005];
	ll& operator [] (ll x){ return x<=100000?a[x]:b[n/x]; } 
}_S,_G,_F;

ll S(ll n){
	if(n<=m) return sigma[n];
	if(_S[n]) return _S[n];
	ll res=0;
	for(ll l=1,r;l<=n;l=r+1){
		r=n/(n/l);
		res=(res+(l+r)%mod*((r-l+1)%mod)%mod*inv2%mod*(n/l%mod))%mod;
	}
	return _S[n]=res;
}

ll G(ll n){
	if(n<=m) return sum[n];
	if(_G[n]) return _G[n];
	ll res=0;
	for(ll i=1;i*i<=n;++i) res=(res+i*(Sqrt(n-i*i)<<1|1))%mod;
	return _G[n]=res;
}

ll F(ll n){
	if(_F[n]) return _F[n];
	ll res=0;
	for(ll l=1,r;l<=n;l=r+1){
		r=n/(n/l);
		res=(res+(S(r)-S(l-1))*G(n/l))%mod;
	}
	return _F[n]=res;
}

int main(){
	scanf("%lld",&n); m=pow(n,0.66); sieve(m);	
	for(ll i=1;i*i<=n;++i) ans=(ans+i*mu[i]*F(n/i/i))%mod;
	printf("%d\n",(ans+mod)%mod);
	return 0;
} 

posted @ 2019-11-06 09:29  pkh68  阅读(235)  评论(0编辑  收藏  举报