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;
}