做这两道题做得心力交瘁,太恶心了,好久没做数学题,套路差点都全忘光了,推式子的时候犯了一堆错:
- 没有注意是否仍然满足乘法分配率
- 模数看错
Problem
求 ∑ i = 1 n ∑ j = 1 m l c m ( i , j ) \sum_{i=1}^n\sum_{j=1}^m lcm(i,j) i=1∑nj=1∑mlcm(i,j)
Solution
变一下原式
∑ i = 1 n ∑ j = 1 m i j gcd ( i , j ) \sum_{i=1}^n\sum_{j=1}^m \frac {ij} {\gcd(i,j)} i=1∑nj=1∑mgcd(i,j)ij
∑ d = 1 n ∑ i = 1 n ∑ j = 1 m [ gcd ( i , j ) = d ] i j d \sum_{d=1}^n \sum_{i=1}^n\sum_{j=1}^m [\gcd(i,j)=d]\frac {ij} d d=1∑ni=1∑nj=1∑m[gcd(i,j)=d]dij
∑ d = 1 n ∑ i = 1 n / d ∑ j = 1 m / d [ gcd ( i , j ) = 1 ] i j d \sum_{d=1}^n \sum_{i=1}^{n/d}\sum_{j=1}^{m/d} [\gcd(i,j)=1] ijd d=1∑ni=1∑n/dj=1∑m/d[gcd(i,j)=1]ijd
∑ d = 1 n d ∑ i = 1 n / d ∑ j = 1 m / d [ gcd ( i , j ) = 1 ] i j \sum_{d=1}^n d\sum_{i=1}^{n/d}\sum_{j=1}^{m/d} [\gcd(i,j)=1] ij d=1∑ndi=1∑n/dj=1∑m/d[gcd(i,j)=1]ij
记 x = n / d , y = m / d x=n/d,y=m/d x=n/d,y=m/d,那么我们来考虑下式怎么计算:
∑ i = 1 x ∑ j = 1 y [ gcd ( i , j ) = 1 ] i j \sum_{i=1}^x\sum_{j=1}^y [\gcd(i,j)=1]ij i=1∑xj=1∑y[gcd(i,j)=1]ij
设 F ( d ) = ∑ i = 1 x ∑ j = 1 y [ gcd ( i , j ) = d ] i j F(d)=\sum_{i=1}^x\sum_{j=1}^y[\gcd(i,j)=d]ij F(d)=i=1∑xj=1∑y[gcd(i,j)=d]ij
G ( x ) = ∑ x ∣ d F ( d ) G(x)=\sum_{x|d} F(d) G(x)=x∣d∑F(d)
通过莫反我们可以知道 F ( n ) = ∑ n ∣ d μ ( d n ) G ( d ) F(n)=\sum_{n|d} \mu(\frac d n)G(d) F(n)=∑n∣dμ(nd)G(d),为了方便表达,我们记 S ( n ) = ∑ i = 1 n i = n ( n + 1 ) 2 S(n)=\sum_{i=1}^n i=\frac {n(n+1)} 2 S(n)=∑i=1ni=2n(n+1)
G ( d ) = ∑ i = 1 x ∑ j = 1 y [ d ∣ gcd ( i , j ) ] i j = d 2 ∑ i = 1 x / d ∑ j = 1 y / d i j = d 2 S ( x d ) S ( y d ) G(d)=\sum_{i=1}^x\sum_{j=1}^y[d|\gcd(i,j)]ij=d^2\sum_{i=1}^{x/d}\sum_{j=1}^{y/d} ij=d^2S(\frac x d)S(\frac y d) G(d)=i=1∑xj=1∑y[d∣gcd(i,j)]ij=d2i=1∑x/dj=1∑y/dij=d2S(dx)S(dy)
我们要求的就是
F
(
1
)
=
∑
i
=
1
x
μ
(
i
)
G
(
i
)
=
∑
i
=
1
x
μ
(
i
)
i
2
S
(
x
i
)
S
(
y
i
)
F(1)=\sum_{i=1}^x \mu(i)G(i)=\sum_{i=1}^x\mu(i) i^2S(\frac x i)S(\frac y i)
F(1)=i=1∑xμ(i)G(i)=i=1∑xμ(i)i2S(ix)S(iy)
数论分块之,一次计算 O ( n ) O(\sqrt n) O(n)
∑ d = 1 n d F ( 1 ) = ∑ d = 1 n d ∑ i = 1 x μ ( i ) G ( i ) \sum_{d=1}^ndF(1)=\sum_{d=1}^nd\sum_{i=1}^{x} \mu(i)G(i) d=1∑ndF(1)=d=1∑ndi=1∑xμ(i)G(i)
∑ d = 1 n d ∑ i = 1 x μ ( i ) i 2 S ( x i ) S ( y i ) \sum_{d=1}^nd\sum_{i=1}^x\mu(i) i^2S(\frac x i)S(\frac y i) d=1∑ndi=1∑xμ(i)i2S(ix)S(iy)
对 x x x分块,然后调用上一个讨论的计算函数计算后面式子的值
O ( n × n ) = O ( n ) O(\sqrt n\times \sqrt n)=O(n) O(n×n)=O(n)
Code
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=10000010,mod=20101009;
template <typename Tp> inline int getmin(Tp &x,Tp y){return y<x?x=y,1:0;}
template <typename Tp> inline int getmax(Tp &x,Tp y){return y>x?x=y,1:0;}
template <typename Tp> inline void read(Tp &x)
{
x=0;int f=0;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
if(f) x=-x;
}
int n,m,tot,ans,pri[maxn],vis[maxn],mu[maxn],sqr[maxn];
int pls(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
void init()
{
mu[1]=1;
for(int i=2;i<=n;i++)
{
if(!vis[i]) mu[i]=mod-1,pri[++tot]=i;
for(int j=1;j<=tot&&i*pri[j]<=n;j++)
{
vis[i*pri[j]]=1;
mu[i*pri[j]]=dec(0,mu[i]);
if(i%pri[j]==0){mu[i*pri[j]]=0;break;}
}
}
for(int i=1;i<=n;i++) sqr[i]=(sqr[i-1]+(ll)i*i%mod*mu[i])%mod;
}
int query(int x,int y)
{
int res=0;
for(int i=1,j,tmp;i<=x;i=j+1)
{
j=min(x/(x/i),y/(y/i));
tmp=((ll)(x/i+1)*(x/i)/2%mod)*((ll)(y/i+1)*(y/i)/2%mod)%mod;
res=(res+(ll)tmp*dec(sqr[j],sqr[i-1]))%mod;
}
return res;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
read(n);read(m);
if(n>m) swap(n,m);
init();
for(int i=1,j,tmp;i<=n;i=j+1)
{
j=min(n/(n/i),m/(m/i));
tmp=(ll)(i+j)*(j-i+1)/2%mod;
ans=(ans+(ll)tmp*query(n/i,m/i))%mod;
}
printf("%d\n",ans);
return 0;
}
Problem
BZOJ2693
同上题,有
1
0
4
10^4
104组询问。
Solution
直接拿之前那题的结论接着做:
∑
d
=
1
n
d
∑
i
=
1
n
/
d
μ
(
i
)
i
2
S
(
n
i
d
)
S
(
m
i
d
)
\sum_{d=1}^n d\sum_{i=1}^{n/d} \mu(i)i^2 S(\frac n {id})S(\frac m {id})
d=1∑ndi=1∑n/dμ(i)i2S(idn)S(idm)
枚举 i d id id
∑ i d = 1 n S ( n i d ) S ( m i d ) ∑ i ∣ i d μ ( i ) i 2 × i d i \sum_{id=1}^nS(\frac n {id}) S(\frac m {id})\sum_{i|id} \mu(i)i^2\times \frac {id} i id=1∑nS(idn)S(idm)i∣id∑μ(i)i2×iid
∑ i d = 1 n S ( n i d ) S ( m i d ) ∑ i ∣ i d i d μ ( i ) i \sum_{id=1}^nS(\frac n {id}) S(\frac m {id})\sum_{i|id} id\mu(i)i id=1∑nS(idn)S(idm)i∣id∑idμ(i)i
后面的是个积性函数,前面的数论分块。
注意 i d id id不能拆出第二个求和,否则会不满足乘法分配率导致分块做的前缀和有问题。。
时间复杂度 O ( n + m n ) O(n+m\sqrt n) O(n+mn)
Code
#include <algorithm>
#include <cstdio>
using namespace std;
typedef long long ll;
const int maxn=10000010,mod=1e8+9;
template <typename Tp> inline int getmin(Tp &x,Tp y){return y<x?x=y,1:0;}
template <typename Tp> inline int getmax(Tp &x,Tp y){return y>x?x=y,1:0;}
template <typename Tp> inline void read(Tp &x)
{
x=0;int f=0;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
if(f) x=-x;
}
int z,n,m,tot,ans,pri[maxn],vis[maxn],val[maxn];
int pls(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int dec(int x,int y){return x-y<0?x-y+mod:x-y;}
void init()
{
val[1]=1;
for(int i=2;i<=10000000;i++)
{
if(!vis[i]) val[i]=dec(i,(ll)i*i%mod),pri[++tot]=i;
for(int j=1;j<=tot&&i*pri[j]<=10000000;j++)
{
vis[i*pri[j]]=1;
if(i%pri[j]==0){val[i*pri[j]]=(ll)val[i]*pri[j]%mod;break;}
val[i*pri[j]]=(ll)val[i]*val[pri[j]]%mod;
}
}
for(int i=2;i<=10000000;i++) val[i]=pls(val[i],val[i-1]);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
#endif
read(z);
init();
while(z--)
{
read(n);read(m);ans=0;
if(n>m) swap(n,m);
for(int i=1,j,tmp;i<=n;i=j+1)
{
j=min(n/(n/i),m/(m/i));
tmp=((ll)(n/i)*(n/i+1)/2%mod)*((ll)(m/i)*(m/i+1)/2%mod)%mod;
ans=(ans+(ll)tmp*dec(val[j],val[i-1]))%mod;
}
printf("%d\n",ans);
}
return 0;
}