**~~
**~~
参考: 1 2
const int MAX_N=;
bool is_prime[MAX_N];
int prime[MAX_N],cntp=0,mu[MAX_N];//prime为范围内的素数
void Moblus()
{
repi(i,2,MAX_N-1) is_prime[i]=true; mu[1]=1;
repi(i,2,MAX_N-1){
if(is_prime[i]) prime[++cntp]=i,mu[i]=-1;
repi(j,1,cntp){
if(i*prime[j]>MAX_N) break;
is_prime[i*prime[j]]=false;
if(i%prime[j]==0){
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
}
公式化简套路
注:一下存在n,m双界时均假设 n < m n
(1) ∑ d ∣ n μ ( d ) = [ n = 1 ] ↔ ∑ d ∣ n μ ( d ) = [ g c d ( i , j ) = 1 ] \sum_{d|n}\mu(d)=[n=1] \leftrightarrow \sum_{d|n}\mu(d)=[gcd(i,j)=1] ∑d∣nμ(d)=[n=1]↔∑d∣nμ(d)=[gcd(i,j)=1]
(2) ∑ i = 1 n ∑ i = 1 m [ g c d ( i , j ) = 1 ] \sum_{i=1}^n\sum_{i=1}^m[gcd(i,j)=1] ∑i=1n∑i=1m[gcd(i,j)=1]
代入式(1)得
= ∑ i = 1 n ∑ i = 1 m ∑ d ∣ g c d ( i , j ) μ ( d ) =\sum_{i=1}^n\sum_{i=1}^m\sum_{d|gcd(i,j)}\mu(d) =∑i=1n∑i=1m∑d∣gcd(i,j)μ(d)
后枚举d,考虑i,j实际均为d的倍数,得
= ∑ d = 1 n μ ( d ) ∑ i = 1 ⌊ n d ⌋ 1 ∑ i = 1 ⌊ m d ⌋ 1 =\sum_{d=1}^n\mu(d)\sum_{i=1}^{\left \lfloor \frac{n}{d} \right \rfloor}1\sum_{i=1}^{\left \lfloor \frac{m}{d} \right \rfloor}1 =∑d=1nμ(d)∑i=1⌊dn⌋1∑i=1⌊dm⌋1
即
= ∑ d = 1 n μ ( d ) ⌊ n d ⌋ ⌊ m d ⌋ =\sum_{d=1}^n\mu(d){\left \lfloor \frac{n}{d} \right \rfloor}{\left \lfloor \frac{m}{d} \right \rfloor} =∑d=1nμ(d)⌊dn⌋⌊dm⌋
(3) ∑ i = 1 n ∑ i = 1 m [ g c d ( i , j ) = k ] \sum_{i=1}^n\sum_{i=1}^m[gcd(i,j)=k] ∑i=1n∑i=1m[gcd(i,j)=k]
同除k,得
= ∑ i = 1 ⌊ n k ⌋ ∑ i = 1 ⌊ m k ⌋ [ g c d ( i , j ) = 1 ] =\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{i=1}^{\left \lfloor \frac{m}{k} \right \rfloor}[gcd(i,j)=1] =∑i=1⌊kn⌋∑i=1⌊km⌋[gcd(i,j)=1]
这样就成(2)了
(4) ∑ i = 1 n ∑ i = 1 m i j [ g c d ( i , j ) = k ] \sum_{i=1}^n\sum_{i=1}^mij[gcd(i,j)=k] ∑i=1n∑i=1mij[gcd(i,j)=k]
类似(3),同除k,但因i,j的缘故需 ∗ k 2 *k^2 ∗k2(i,j每个贡献一个k)
= ∑ i = 1 ⌊ n k ⌋ ∑ i = 1 ⌊ m k ⌋ i j [ g c d ( i , j ) = 1 ] ∗ k 2 =\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{i=1}^{\left \lfloor \frac{m}{k} \right \rfloor}ij[gcd(i,j)=1]*k^2 =∑i=1⌊kn⌋∑i=1⌊km⌋ij[gcd(i,j)=1]∗k2
接下来用(1)替换 [ g c d ( i , j ) = 1 ] [gcd(i,j)=1] [gcd(i,j)=1],得
= ∑ i = 1 ⌊ n k ⌋ ∑ i = 1 ⌊ m k ⌋ i j ∑ d ∣ g c d ( i , j ) μ ( d ) ∗ k 2 =\sum_{i=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\sum_{i=1}^{\left \lfloor \frac{m}{k} \right \rfloor}ij\sum_{d|gcd(i,j)}\mu(d)*k^2 =∑i=1⌊kn⌋∑i=1⌊km⌋ij∑d∣gcd(i,j)μ(d)∗k2
换为枚举d,并调换顺序,得( d 2 d^2 d2和上面 k 2 k^2 k2原因相同,均为i,j贡献)
= k 2 ∗ ∑ d = 1 ⌊ n k ⌋ μ ( d ) ∗ d 2 ∑ i = 1 ⌊ n k d ⌋ i ∑ i = 1 ⌊ m k d ⌋ j =k^2*\sum_{d=1}^{\left \lfloor \frac{n}{k} \right \rfloor}\mu(d)*d^2\sum_{i=1}^{\left \lfloor \frac{n}{kd} \right \rfloor}i\sum_{i=1}^{\left \lfloor \frac{m}{kd} \right \rfloor}j =k2∗∑d=1⌊kn⌋μ(d)∗d2∑i=1⌊kdn⌋i∑i=1⌊kdm⌋j
注意到后两项实际为等差数列求和 o ( 1 ) o(1) o(1),此时整体复杂度 o ( n ) o(n) o(n)
(5) ∑ i = 1 n ∑ i = 1 m l c m ( i , j ) \sum_{i=1}^n\sum_{i=1}^mlcm(i,j) ∑i=1n∑i=1mlcm(i,j)
首先将lcm替换为熟悉的gcd l c m ( i , j ) = i ∗ j g c d ( i , j ) ) lcm(i,j)=\frac{i*j}{gcd(i,j))} lcm(i,j)=gcd(i,j))i∗j,得
= ∑ i = 1 n ∑ i = 1 m i ∗ j g c d ( i , j ) ) =\sum_{i=1}^n\sum_{i=1}^m\frac{i*j}{gcd(i,j))} =∑i=1n∑i=1mgcd(i,j))i∗j
枚举gcd,得
= ∑ d = 1 n ∑ i = 1 n ∑ i = 1 m i ∗ j d ∗ [ g c d ( i , j ) = d ] =\sum_{d=1}^n\sum_{i=1}^n\sum_{i=1}^m\frac{i*j}{d}*[gcd(i,j)=d] =∑d=1n∑i=1n∑i=1mdi∗j∗[gcd(i,j)=d]
同除d,并替换 [ g c d ( i , j ) = 1 ] [gcd(i,j)=1] [gcd(i,j)=1]
= ∑ d = 1 n ∑ i = 1 ⌊ n d ⌋ ∑ i = 1 ⌊ m d ⌋ i j ∗ d ∑ k ∣ g c d ( i , j ) μ ( k ) =\sum_{d=1}^n\sum_{i=1}^{\left \lfloor \frac{n}{d} \right \rfloor}\sum_{i=1}^{\left \lfloor \frac{m}{d} \right \rfloor}ij*d\sum_{k|gcd(i,j)}\mu(k) =∑d=1n∑i=1⌊dn⌋∑i=1⌊dm⌋ij∗d∑k∣gcd(i,j)μ(k)
枚举k,得
= ∑ d = 1 n d ∑ k = 1 ⌊ n d ⌋ μ ( k ) ∗ k 2 ∑ i = 1 ⌊ n d k ⌋ i ∑ i = 1 ⌊ m d k ⌋ j =\sum_{d=1}^nd\sum_{k=1}^{{\left \lfloor \frac{n}{d} \right \rfloor}}\mu(k)*k^2\sum_{i=1}^{\left \lfloor \frac{n}{dk} \right \rfloor}i\sum_{i=1}^{\left \lfloor \frac{m}{dk} \right \rfloor}j =∑d=1nd∑k=1⌊dn⌋μ(k)∗k2∑i=1⌊dkn⌋i∑i=1⌊dkm⌋j
此时通过对 ∑ k = 1 ⌊ n d ⌋ \sum_{k=1}^{{\left \lfloor \frac{n}{d} \right \rfloor}} ∑k=1⌊dn⌋分块, ∑ i = 1 ⌊ n d k ⌋ i ∑ i = 1 ⌊ m d k ⌋ j \sum_{i=1}^{\left \lfloor \frac{n}{dk} \right \rfloor}i\sum_{i=1}^{\left \lfloor \frac{m}{dk} \right \rfloor}j ∑i=1⌊dkn⌋i∑i=1⌊dkm⌋j分块,复杂度 o ( n ∗ n ) = o ( n ) o(\sqrt{n}*\sqrt{n})=o(n) o(n∗n)=o(n)
进一步优化,设 T = d k , f ( x ) = ∑ i x i T=dk,f(x)=\sum_i^xi T=dk,f(x)=∑ixi
= ∑ d = 1 n d ∑ k = 1 ⌊ n d ⌋ μ ( k ) ∗ k 2 ∗ f ( ⌊ n T ⌋ ) ∗ f ( ⌊ m T ⌋ ) =\sum_{d=1}^nd\sum_{k=1}^{{\left \lfloor \frac{n}{d} \right \rfloor}}\mu(k)*k^2*f(\left \lfloor \frac{n}{T} \right \rfloor)*f(\left \lfloor \frac{m}{T} \right \rfloor) =∑d=1nd∑k=1⌊dn⌋μ(k)∗k2∗f(⌊Tn⌋)∗f(⌊Tm⌋)
枚举T,得
= ∑ T = 1 n f ( ⌊ n T ⌋ ) ∗ f ( ⌊ m T ⌋ ) ∑ d ∣ T d ∗ μ ( T d ) ∗ ( T d ) 2 =\sum_{T=1}^nf(\left \lfloor \frac{n}{T} \right \rfloor)*f(\left \lfloor \frac{m}{T} \right \rfloor)\sum_{d|T}d*\mu(\frac{T}{d})*(\frac{T}{d})^2 =∑T=1nf(⌊Tn⌋)∗f(⌊Tm⌋)∑d∣Td∗μ(dT)∗(dT)2
令 d = T / d , T / d = d d=T/d,T/d=d d=T/d,T/d=d,得
= ∑ T = 1 n f ( ⌊ n T ⌋ ) ∗ f ( ⌊ m T ⌋ ) ∑ d ∣ T d ∗ μ ( d ) ∗ T =\sum_{T=1}^nf(\left \lfloor \frac{n}{T} \right \rfloor)*f(\left \lfloor \frac{m}{T} \right \rfloor)\sum_{d|T}d*\mu(d)*T =∑T=1nf(⌊Tn⌋)∗f(⌊Tm⌋)∑d∣Td∗μ(d)∗T
此时观察最后这个式子 f ( T ) = ∑ d ∣ T d ∗ μ ( d ) ∗ T f(T)=\sum_{d|T}d*\mu(d)*T f(T)=∑d∣Td∗μ(d)∗T,考虑对 a ⊥ b a\perp b a⊥b
f ( a ) ∗ f ( b ) f(a)*f(b) f(a)∗f(b)
= ∑ d ∣ a d ∗ μ ( d ) ∗ a ∑ d ∣ b d ∗ μ ( d ) ∗ b =\sum_{d|a}d*\mu(d)*a\sum_{d|b}d*\mu(d)*b =∑d∣ad∗μ(d)∗a∑d∣bd∗μ(d)∗b
a,b互质,则不存在一个d同时为a,b的因数,而每个a,b的d相乘,可构成ab的所有因数,同时 μ \mu μ也是积性函数,得
= ∑ d ∣ a b d ∗ μ ( d ) ∗ a b =\sum_{d|ab}d*\mu(d)*ab =∑d∣abd∗μ(d)∗ab
= f ( a b ) =f(ab) =f(ab)
即 f f f为积性函数,可线性筛对 f f f预处理,同时处理出其前缀和,设 p p p为素数
其中 f ( 1 ) = 1 , f ( p ) = f ( p k ) = 1 − p f(1)=1,f(p)=f(p^k)=1-p f(1)=1,f(p)=f(pk)=1−p
此时就只有一次分块 o ( n ) → o ( n ) o(n)\rightarrow o(\sqrt n) o(n)→o(n)
(6) ∑ i = 1 n ∑ j = 1 m g c d ( i , j ) k \sum_{i=1}^n\sum_{j=1}^mgcd(i,j)^k ∑i=1n∑j=1mgcd(i,j)k
枚举gcd,得
= ∑ i = 1 n ∑ j = 1 m ∑ d = 1 n d k [ g c d ( i , j ) = d ] =\sum_{i=1}^n\sum_{j=1}^m\sum_{d=1}^nd^k[gcd(i,j)=d] =∑i=1n∑j=1m∑d=1ndk[gcd(i,j)=d]
= ∑ d = 1 n d k ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ [ g c d ( i , j ) = 1 ] =\sum_{d=1}^nd^k\sum_{i=1}^{\left \lfloor \frac{n}{d} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{m}{d} \right \rfloor}[gcd(i,j)=1] =∑d=1ndk∑i=1⌊dn⌋∑j=1⌊dm⌋[gcd(i,j)=1]
将 [ g c d ( i , j ) = 1 ] [gcd(i,j)=1] [gcd(i,j)=1]换掉,得
= ∑ d = 1 n d k ∑ i = 1 ⌊ n d ⌋ ∑ i = 1 ⌊ m d ⌋ ∑ x ∣ g c d ( i , j ) μ ( x ) =\sum_{d=1}^nd^k\sum_{i=1}^{\left \lfloor \frac{n}{d}\right \rfloor}\sum_{i=1}^{\left \lfloor \frac{m}{d}\right \rfloor}\sum_{x|gcd(i,j)}\mu(x) =∑d=1ndk∑i=1⌊dn⌋∑i=1⌊dm⌋∑x∣gcd(i,j)μ(x)
枚举x,得
= ∑ d = 1 n d k ∑ x = 1 ⌊ n d ⌋ μ ( x ) ⌊ n d x ⌋ ⌊ m d x ⌋ =\sum_{d=1}^nd^k\sum_{x=1}^{\left \lfloor \frac{n}{d}\right \rfloor}\mu(x)\left \lfloor \frac{n}{dx}\right \rfloor\left \lfloor \frac{m}{dx}\right \rfloor =∑d=1ndk∑x=1⌊dn⌋μ(x)⌊dxn⌋⌊dxm⌋
设T=dx,枚举T,x=T/d
= ∑ T = 1 n ⌊ n T ⌋ ⌊ m T ⌋ ∑ d ∣ T d k μ ( T d ) =\sum_{T=1}^n\left \lfloor \frac{n}{T}\right \rfloor\left \lfloor \frac{m}{T}\right \rfloor\sum_{d|T}d^k\mu(\frac{T}{d}) =∑T=1n⌊Tn⌋⌊Tm⌋∑d∣Tdkμ(dT)
设 f ( T ) = ∑ d ∣ T d k μ ( T d ) f(T)=\sum_{d|T}d^k\mu(\frac{T}{d}) f(T)=∑d∣Tdkμ(dT)
其中 f ( x ) f(x) f(x)相当于 g ( x ) = x k g(x)=x^k g(x)=xk与莫比武器函数的狄利克雷卷积,二者均为积性函数,故 f ( x ) f(x) f(x)也为积性函数
考虑积性函数的线性筛,设 p p p为质数
f ( 1 ) = 1 f(1)=1 f(1)=1
f ( p ) = p k − 1 f(p)=p^k-1 f(p)=pk−1
f ( p a ) = p a k f(p^a)=p^{ak} f(pa)=pak − p ( a − 1 ) ∗ k -p^{(a-1)*k} −p(a−1)∗k( μ \mu μ取值1和-1分别对应 p a , p a − 1 p^a,p^{a-1} pa,pa−1)
筛出 f f f函数后求其前缀和,再分块处理即可
(7) ∏ i = 1 n ∏ j = 1 m F g c d ( i , j ) \prod_{i=1}^n\prod_{j=1}^mF_{gcd(i,j)} ∏i=1n∏j=1mFgcd(i,j),其中 F i F_i Fi为斐波那契数列第i项
= ∏ k = 1 n F k ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = k ] =\prod_{k=1}^nF_k^{\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=k]} =∏k=1nFk∑i=1n∑j=1m[gcd(i,j)=k]
对式中F指数部分,常见的除k并换掉 [ g c d ( i , j ) = 1 ] [gcd(i,j)=1] [gcd(i,j)=1],得
= ∑ d = 1 ⌊ n k ⌋ μ ( d ) ∗ ⌊ n k d ⌋ ∗ ⌊ m k d ⌋ =\sum_{d=1}^{\left \lfloor \frac{n}{k}\right \rfloor}\mu(d)*\left \lfloor \frac{n}{kd}\right \rfloor*\left \lfloor \frac{m}{kd}\right \rfloor =∑d=1⌊kn⌋μ(d)∗⌊kdn⌋∗⌊kdm⌋
代入原式,得
= ∏ k = 1 n F k ∑ d = 1 ⌊ n k ⌋ μ ( d ) ∗ ⌊ n k d ⌋ ∗ ⌊ m k d ⌋ =\prod_{k=1}^nF_k^{\sum_{d=1}^{\left \lfloor \frac{n}{k}\right \rfloor}\mu(d)*\left \lfloor \frac{n}{kd}\right \rfloor*\left \lfloor \frac{m}{kd}\right \rfloor} =∏k=1nFk∑d=1⌊kn⌋μ(d)∗⌊kdn⌋∗⌊kdm⌋
设T=kd,枚举T,得
= ∏ T = 1 n ( ∏ k ∣ T F k μ ( T k ) ) ⌊ n T ⌋ ∗ ⌊ m T ⌋ =\prod_{T=1}^n(\prod_{k|T}F_k^{\mu(\frac{T}{k})})^{\left \lfloor \frac{n}{T} \right \rfloor*\left \lfloor \frac{m}{T} \right \rfloor} =∏T=1n(∏k∣TFkμ(kT))⌊Tn⌋∗⌊Tm⌋
设 f ( n ) = ∏ d ∣ n F d μ ( n k ) f(n)=\prod_{d|n}F_d^{\mu(\frac{n}{k})} f(n)=∏d∣nFdμ(kn),则原式化为
= ∏ T = 1 n f ( T ) ⌊ n T ⌋ ∗ ⌊ m T ⌋ =\prod_{T=1}^nf(T)^{\left \lfloor \frac{n}{T} \right \rfloor*\left \lfloor \frac{m}{T} \right \rfloor} =∏T=1nf(T)⌊Tn⌋∗⌊Tm⌋
对外层的 ∏ \prod ∏,分块处理, f f f函数预处理即可(每个数的贡献计入其倍数中, o ( n l o g n ) o(nlogn) o(nlogn))
(8) d ( n m ) = ∑ i ∣ n ∑ j ∣ m [ g c d ( i , j ) = 1 ] d(nm)=\sum_{i|n}\sum_{j|m}[gcd(i,j)=1] d(nm)=∑i∣n∑j∣m[gcd(i,j)=1] (假设 d d d为约数个数和函数)
证明: n m nm nm的每个约数均可表示为 i ∗ m j i*\frac{m}{j} i∗jm的式,限制 g c d ( i , j ) = 1 gcd(i,j)=1 gcd(i,j)=1防止计重(若不为1,为k,则存在 i k 和 j k \frac{i}{k}和\frac{j}{k} ki和kj的情况,此时二者表示的约数相同)
推广: d ( n m t ) = ∑ i ∣ n ∑ j ∣ m ∑ k ∣ t [ g c d ( i , j ) = g c d ( i , k ) = g c d ( j , k ) = 1 ] d(nmt)=\sum_{i|n}\sum{j|m}\sum_{k|t}[gcd(i,j)=gcd(i,k)=gcd(j,k)=1] d(nmt)=∑i∣n∑j∣m∑k∣t[gcd(i,j)=gcd(i,k)=gcd(j,k)=1]
例题
1.hdu1695
给出 a , b , c , d , k a,b,c,d,k a,b,c,d,k,问 x ∈ [ a , b ] , y ∈ [ c , d ] , g c d ( x , y ) = k x\in[a,b],y\in[c,d],gcd(x,y)=k x∈[a,b],y∈[c,d],gcd(x,y)=k的对数,其中 a = c = 1 , g c d ( x , y ) a=c=1,gcd(x,y) a=c=1,gcd(x,y)于 g c d ( y , x ) gcd(y,x) gcd(y,x)视为相同对不重复计数
相当于套路(3),只是这里需要考虑计重的问题,设 n < m n
另一个思考的角度:
设 f ( d ) f(d) f(d)为有多少对 ( x , y ) (x,y) (x,y)使 g c d ( x , y ) = d gcd(x,y)=d gcd(x,y)=d。 F ( d ) F(d) F(d)为有多少对(x,y)使 g c d ( x , y ) = d gcd(x,y)=d gcd(x,y)=d的倍数,
显然, F ( d ) F(d) F(d)更好算,因为 F ( d ) = ( ( b / k ) / d ) ∗ ( ( d / k ) / d ) F(d)=((b/k)/d)*((d/k)/d) F(d)=((b/k)/d)∗((d/k)/d)
利用莫比乌斯反演公式的倍数形式, f ( n ) = ∑ n ∣ d μ ( d n ) F ( d ) f(n)=\sum_{n|d}\mu(\frac{d}{n})F(d) f(n)=∑n∣dμ(nd)F(d),计算 f ( 1 ) f(1) f(1)且 d = 1 , 2 … … m i n ( b / k , d / k ) d=1,2……min(b/k,d/k) d=1,2……min(b/k,d/k)(即倍数形式中所提到的上界)即可。
ll a,b,c,d,k;
int main()
{
Moblus();
int T,cas=1;
si(T);
while(T--)
{
sl(a),sl(b),sl(c),sl(d),sl(k);
printf("Case %d: ",cas++);
if(!k) puts("0");
else{
ll ans1=0,ans2=0;
b/=k,d/=k;
repi(i,1,min(b,d)) ans1+=mu[i]*(b/i)*(d/i);//这里可以用前缀和+分块加速o(sqrt(n))
repi(i,1,min(b,d)) ans2+=mu[i]*(min(b,d)/i)*(min(b,d)/i);
ans1-=ans2/2;
printf("%lld\n",ans1);
}
}
return 0;
}
2.P2522
问题同上一问,但没有不计重的限制与 a = c = 1 a=c=1 a=c=1的条件
容斥一下(类似二位前缀和)
int k;
ll solve(int n,int m)
{
n/=k,m/=k;
if(n>m) swap(n,m);
ll res=0;
for(int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
res+=1ll*(n/l)*(m/l)*(sum[r]-sum[l-1]);//sum为莫比乌斯函数前缀和
}
return res;
}
int main()
{
Moblus();
int T; si(T);
while(T--)
{
int a,b,c,d; si(a),si(b),si(c),si(d),si(k);
ll ans=solve(b,d)-solve(a-1,d)-solve(b,c-1)+solve(a-1,c-1);
printf("%lld\n",ans);
}
return 0;
}
3.hdu2841
有一个 n ∗ m n*m n∗m的网格,人在(0,0)问有几个格点(坐标值不可为0)可以被看到
什么情况下会看不到呢? g c d ( x , y ) ! = 1 gcd(x,y)!=1 gcd(x,y)!=1,相当于求 ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = 1 ] \sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=1] ∑i=1n∑j=1m[gcd(i,j)=1],按套路(2)处理即可
int main()
{
Moblus();
int T; si(T);
while(T--)
{
int n,m; si(n),si(m);
ll ans=0;
repi(i,1,min(n,m)) ans+=1ll*mu[i]*(n/i)*(m/i);
printf("%lld\n",ans);
}
return 0;
}
4.Visible Lattice Points
上一个问题扩展为3维的情况(另外,坐标值可为0),空间大小 n ∗ n ∗ n n*n*n n∗n∗n
对坐标值 1 − n 1-n 1−n的情况,类似上一问处理
考虑 x , y , z x,y,z x,y,z一个为0,则就等同于二维,即上一问情况,
2个为零,易知只有3个点( ( 0 , 0 , 1 ) , ( 0 , 1 , 0 ) , ( 1 , 0 , 0 ) (0,0,1),(0,1,0),(1,0,0) (0,0,1),(0,1,0),(1,0,0))满足
int main()
{
Moblus();
int T; si(T);
while(T--)
{
int n; si(n);
ll ans=0;
repi(i,1,n) ans+=1ll*mu[i]*(n/i)*(n/i)*(n/i+3);
printf("%lld\n",ans+3);
}
return 0;
}
5.P1829
套路(5) ∑ i = 1 n ∑ i = 1 m l c m ( i , j ) \sum_{i=1}^n\sum_{i=1}^mlcm(i,j) ∑i=1n∑i=1mlcm(i,j) 对应的题
单次询问 o ( n ) o(n) o(n)的算法
typedef long long ll;
const int MAX_N=1e7+5;
const int mod=20101009;
const int inv2=10050505;
bool check[MAX_N];
int prime[MAX_N/10],cntp=0,mu[MAX_N];//primeΪ·¶Î§ÄÚµÄËØÊý
ll sum[MAX_N];
void Moblus()
{
ms(check),mu[1]=1;
repi(i,2,MAX_N-1){
if(!check[i]) prime[++cntp]=i*1ll,mu[i]=-1;
repi(j,1,cntp){
if(i*prime[j]>MAX_N) break;
check[i*prime[j]]=true;
if(i%prime[j]==0){
mu[i*prime[j]]=0;
break;
}
else mu[i*prime[j]]=-mu[i];
}
}
repi(i,1,MAX_N-1) sum[i]=(sum[i-1]+1ll*i*i%mod*mu[i]%mod)%mod;
}
ll cal(int x)
{
return 1ll*x*(x+1)%mod*inv2%mod;
}
ll solve(int n,int m)
{
ll ans=0;
for(int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
ans=(ans+(sum[r]-sum[l-1])*cal(n/l)%mod*cal(m/l)%mod)%mod;
}
return ans;
}
int main()
{
Moblus();
int n,m; si(n),si(m);
if(n>m) swap(n,m);
ll ans=0;
for(int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
ans=(ans+1ll*(l+r)*(r-l+1)%mod*inv2%mod*solve(n/l,m/l)%mod)%mod;
}
printf("%lld\n",(ans%mod+mod)%mod);
return 0;
}
单次询问 o ( n ) o(\sqrt n) o(n)的算法
typedef long long ll;
const int MAX_N=1e7+5;
const int mod=20101009;
const int inv2=10050505;
bool is_prime[MAX_N];
int prime[MAX_N],cntp=0;
int f[MAX_N],sum[MAX_N],low[MAX_N];//f£ºËùÇó»ýÐÔº¯Êý sum£ºfǰ׺ºÍ low£ºi¶ÔÓ¦×îСÖÊÒò×Óp^a
void mf_sieve(int MAX_N)
{
repi(i,2,MAX_N-1) is_prime[i]=true;
f[1]=sum[1]=1;//¸ù¾Ý¾ßÌ庯Êý³õʼ»¯
repi(i,2,MAX_N-1){
if(is_prime[i]) prime[++cntp]=i,low[i]=i,f[i]=1-i;//¸ù¾Ý¾ßÌ庯Êý³õʼ»¯£¨¼´ÖÊÊý¶ÔÓ¦µÄº¯ÊýÖµ£©
for(int j=1;j<=cntp&&i*prime[j]<MAX_N;j++){
is_prime[i*prime[j]]=false;
if(i%prime[j]==0){
low[i*prime[j]]=low[i]*prime[j];
if(low[i]==i) f[i*prime[j]]=1-prime[j];//´ËʱiΪij¸öÖÊÊýµÄÈô¸É´ÎÃÝ£¬f(p^k) low[i]=p^a i%prime[j]=0 => p=prime[j]
else f[i*prime[j]]=1ll*f[i/low[i]]*f[low[i]*prime[j]]%mod;
break;
}
low[i*prime[j]]=prime[j];
f[i*prime[j]]=1ll*f[i]*f[prime[j]]%mod;
}
sum[i]=(1ll*sum[i-1]+1ll*f[i]*i)%mod;
}
}
int cal(int x){return 1ll*(1+x)*x%mod*inv2%mod;}
int main()
{
int n,m; si(n),si(m);
mf_sieve(max(n,m)+1);
if(n>m) swap(n,m);
int ans=0;
for(int l=1,r;l<=n;l=r+1){
r=min(n/(n/l),m/(m/l));
ans=(1ll*ans+1ll*cal(n/l)*cal(m/l)%mod*(sum[r]-sum[l-1])%mod)%mod;
}
printf("%d\n",(ans%mod+mod)%mod);
return 0;
}
6.P4449
套路(6) ∑ i = 1 n ∑ j = 1 m g c d ( i , j ) k \sum_{i=1}^n\sum_{j=1}^mgcd(i,j)^k ∑i=1n∑j=1mgcd(i,j)k对应的题
const int MAX_N=5e6+5;
const int mod=1e9+7;
ll qpow(ll x,ll n,ll mod){ ll res=1;while(n){ if(n&1) res=(res*x)%mod; x=x*x%mod,n>>=1; } return res; }
bool is_prime[MAX_N];
int prime[MAX_N],cntp=0;
int f[MAX_N],sum[MAX_N],low[MAX_N];
int n,k;
void mf_sieve()
{
repi(i,2,MAX_N-1) is_prime[i]=true;
f[1]=sum[1]=1;
repi(i,2,MAX_N-1){
if(is_prime[i]) prime[++cntp]=i,f[i]=(qpow(i,k,mod)-1)%mod,low[i]=i;
for(int j=1;j<=cntp&&i*prime[j]<MAX_N;j++){
is_prime[i*prime[j]]=false;
if(i%prime[j]==0){
low[i*prime[j]]=low[i]*prime[j];
if(low[i]==i) f[i*prime[j]]=(qpow(i*prime[j],k,mod)-qpow(i,k,mod)+mod)%mod;
else f[i*prime[j]]=1ll*f[i/low[i]]*f[low[i]*prime[j]]%mod;
break;
}
low[i*prime[j]]=prime[j];
f[i*prime[j]]=1ll*f[i]*f[prime[j]]%mod;
}
sum[i]=(1ll*sum[i-1]+f[i])%mod;
}
}
int main()
{
int T; si(T),si(k);
mf_sieve();
while(T--)
{
int n,m; si(n),si(m);
int ans=0;
for(int l=1,r;l<=min(n,m);l=r+1){
r=min(n/(n/l),m/(m/l));
ans=(ans+1ll*(sum[r]-sum[l-1]+mod)%mod*(n/l)%mod*(m/l)%mod)%mod;
}
printf("%d\n",(ans%mod+mod)%mod);
}
return 0;
}
7.P3704
套路(7) ∏ i = 1 n ∏ j = 1 m F g c d ( i , j ) \prod_{i=1}^n\prod_{j=1}^mF_{gcd(i,j)} ∏i=1n∏j=1mFgcd(i,j)对应的题
const int MAX_N=1e6+5;
const int mod=1e9+7;
ll qpow(ll x,ll n,ll mod){ ll res=1;while(n){ if(n&1) res=(res*x)%mod; x=x*x%mod,n>>=1; } return res; }
bool is_prime[MAX_N];
int prime[MAX_N],cntp=0,mu[MAX_N];//primeΪ·¶Î§ÄÚµÄËØÊý
int f[MAX_N],pm[MAX_N];
void Moblus()
{
f[0]=0,f[1]=1;
repi(i,2,MAX_N-1) is_prime[i]=true,f[i]=(1ll*f[i-1]+f[i-2])%mod; mu[1]=1;
repi(i,2,MAX_N-1){
if(is_prime[i]) prime[++cntp]=i*1ll,mu[i]=-1;
repi(j,1,cntp){
if(i*prime[j]>MAX_N) break;
is_prime[i*prime[j]]=false;
if(i%prime[j]==0){
mu[i*prime[j]]=0;
break;
}
else mu[i*prime[j]]=-mu[i];
}
}
repi(i,0,MAX_N-1) pm[i]=1;
repi(i,1,MAX_N-1){
ll inv=qpow(f[i],mod-2,mod);
for(int j=i;j<MAX_N;j+=i){
if(mu[j/i]==-1) pm[j]=(1ll*pm[j]*inv)%mod;
else if(mu[j/i]==1) pm[j]=(1ll*pm[j]*f[i])%mod;
}
pm[i]=(1ll*pm[i]*pm[i-1])%mod;
}
}
int main()
{
Moblus();
int T; si(T);
while(T--)
{
int n,m; si(n),si(m);
int ans=1;
for(int l=1,r;l<=min(n,m);l=r+1){
r=min(n/(n/l),m/(m/l));
ans=(1ll*ans*qpow(1ll*pm[r]*qpow(pm[l-1],mod-2,mod)%mod,1ll*(n/l)*(m/l),mod))%mod;
}
printf("%d\n",(ans%mod+mod)%mod);
}
return 0;
}
8.P3327
求 ∑ i = 1 n ∑ j = 1 m d ( i j ) \sum_{i=1}^n\sum_{j=1}^md(ij) ∑i=1n∑j=1md(ij), d ( x ) d(x) d(x)为x的约数的个数
代入套路(8) d ( n m ) = ∑ i ∣ n ∑ j ∣ m [ g c d ( i , j ) = 1 ] d(nm)=\sum_{i|n}\sum_{j|m}[gcd(i,j)=1] d(nm)=∑i∣n∑j∣m[gcd(i,j)=1],得
= ∑ p = 1 n ∑ q = 1 m ∑ i ∣ p ∑ j ∣ q [ g c d ( i , j ) = 1 ] =\sum_{p=1}^n\sum_{q=1}^m\sum_{i|p}\sum_{j|q}[gcd(i,j)=1] =∑p=1n∑q=1m∑i∣p∑j∣q[gcd(i,j)=1]
对每对 g c d ( i , j ) = 1 gcd(i,j)=1 gcd(i,j)=1中的 i , j i,j i,j,其对应的p,q实际均为其倍数,即产生 ⌊ n i ⌋ ∗ ⌊ m j ⌋ \left \lfloor \frac{n}{i} \right \rfloor*\left \lfloor \frac{m}{j} \right \rfloor ⌊in⌋∗⌊jm⌋的贡献
= ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = 1 ] ∗ ⌊ n i ⌋ ∗ ⌊ m j ⌋ =\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=1]*\left \lfloor \frac{n}{i} \right \rfloor*\left \lfloor \frac{m}{j} \right \rfloor =∑i=1n∑j=1m[gcd(i,j)=1]∗⌊in⌋∗⌊jm⌋
替换掉 [ g c d ( i , j ) = 1 ] [gcd(i,j)=1] [gcd(i,j)=1],得
= ∑ i = 1 n ∑ j = 1 m ⌊ n i ⌋ ∗ ⌊ m j ⌋ ∑ d ∣ g c d ( i , j ) μ ( d ) =\sum_{i=1}^n\sum_{j=1}^m\left \lfloor \frac{n}{i} \right \rfloor*\left \lfloor \frac{m}{j} \right \rfloor\sum_{d|gcd(i,j)}\mu(d) =∑i=1n∑j=1m⌊in⌋∗⌊jm⌋∑d∣gcd(i,j)μ(d)
枚举d,得(假设 n < m n
= ∑ d = 1 n μ ( d ) ∑ i = 1 ⌊ n d ⌋ ∑ j = 1 ⌊ m d ⌋ ⌊ n i d ⌋ ∗ ⌊ m j d ⌋ =\sum_{d=1}^n\mu(d)\sum_{i=1}^{\left \lfloor \frac{n}{d} \right \rfloor}\sum_{j=1}^{\left \lfloor \frac{m}{d} \right \rfloor}\left \lfloor \frac{n}{id} \right \rfloor*\left \lfloor \frac{m}{jd} \right \rfloor =∑d=1nμ(d)∑i=1⌊dn⌋∑j=1⌊dm⌋⌊idn⌋∗⌊jdm⌋
= ∑ d = 1 n μ ( d ) ∑ i = 1 ⌊ n d ⌋ ⌊ n i d ⌋ ∑ j = 1 ⌊ m d ⌋ ⌊ m j d ⌋ =\sum_{d=1}^n\mu(d)\sum_{i=1}^{\left \lfloor \frac{n}{d} \right \rfloor}\left \lfloor \frac{n}{id} \right \rfloor\sum_{j=1}^{\left \lfloor \frac{m}{d} \right \rfloor}\left \lfloor \frac{m}{jd} \right \rfloor =∑d=1nμ(d)∑i=1⌊dn⌋⌊idn⌋∑j=1⌊dm⌋⌊jdm⌋
设 g ( n ) = ∑ d = 1 n ⌊ n d ⌋ g(n)=\sum_{d=1}^n\left \lfloor \frac{n}{d} \right \rfloor g(n)=∑d=1n⌊dn⌋,得
= ∑ d = 1 n μ ( d ) g ( ⌊ n d ⌋ ) g ( ⌊ m d ⌋ ) =\sum_{d=1}^n\mu(d)g(\left \lfloor \frac{n}{d} \right \rfloor)g(\left \lfloor \frac{m}{d} \right \rfloor) =∑d=1nμ(d)g(⌊dn⌋)g(⌊dm⌋)
下面只需预处理出 g g g及 μ \mu μ前缀和,再进行分块即可,处理 g g g对每个都运用分块求,预处理复杂度 o ( n n ) o(n\sqrt n) o(nn),单次询问复杂度 o ( n ) o(\sqrt n) o(n)
typedef long long ll;
const int MAX_N=5e4+5;
bool check[MAX_N];
int prime[MAX_N],cntp,mu[MAX_N];//primeΪ·¶Î§ÄÚµÄËØÊý
ll g[MAX_N],sum_mu[MAX_N];
void Moblus()
{
ms(check),mu[1]=1;
int tot=0;
repi(i,2,MAX_N-1){
if(!check[i]) prime[++tot]=i*1ll,mu[i]=-1;
repi(j,1,tot){
if(i*prime[j]>MAX_N) break;
check[i*prime[j]]=true;
if(i%prime[j]==0){
mu[i*prime[j]]=0;
break;
}
else mu[i*prime[j]]=-mu[i];
}
}
sum_mu[0]=0;
repi(i,1,MAX_N-1) sum_mu[i]=sum_mu[i-1]+mu[i];
repi(i,1,MAX_N-1){
for(ll l=1,r;l<=i;l=r+1){
r=i/(i/l);
g[i]+=1ll*(r-l+1)*(i/l);
}
}
}
ll solve(int n,int m)
{
if(n<m) swap(n,m);
ll ans=0;
for(ll l=1,r;l<=m;l=r+1){
r=min(n/(n/l),m/(m/l));
ans+=(sum_mu[r]-sum_mu[l-1])*g[n/l]*g[m/l];
}
return ans;
}
int main()
{
Moblus();
int T; si(T);
while(T--)
{
int n,m; si(n),si(m);
printf("%lld\n",solve(n,m));
}
return 0;
}
9.CodeForces-235E
求 ∑ i = 1 a ∑ j = 1 b ∑ k = 1 c d ( i j k ) \sum_{i=1}^a\sum_{j=1}^b\sum_{k=1}^cd(ijk) ∑i=1a∑j=1b∑k=1cd(ijk), d ( x ) d(x) d(x)为x的约数的个数
代入套路(8)推广
= ∑ i = 1 a ∑ j = 1 b ∑ k = 1 c ∑ i ∣ a ∑ j ∣ b ∑ k ∣ c [ g c d ( i , j ) = 1 ] [ g c ( j , k ) = 1 ] [ g c d ( i , k ) = 1 ] =\sum_{i=1}^a\sum_{j=1}^b\sum_{k=1}^c\sum_{i|a}\sum_{j|b}\sum_{k|c}[gcd(i,j)=1][gc(j,k)=1][gcd(i,k)=1] =∑i=1a∑j=1b∑k=1c∑i∣a∑j∣b∑k∣c[gcd(i,j)=1][gc(j,k)=1][gcd(i,k)=1]
= ∑ i = 1 a ∑ j = 1 b ∑ k = 1 c ⌊ a i ⌋ ⌊ b j ⌋ ⌊ c k ⌋ [ g c d ( i , j ) = 1 ] [ g c d ( j , k ) = 1 ] [ g c d ( i , k ) = 1 ] =\sum_{i=1}^a\sum_{j=1}^b\sum_{k=1}^c\left \lfloor \frac{a}{i} \right \rfloor\left \lfloor \frac{b}{j} \right \rfloor\left \lfloor \frac{c}{k} \right \rfloor[gcd(i,j)=1][gcd(j,k)=1][gcd(i,k)=1] =∑i=1a∑j=1b∑k=1c⌊ia⌋⌊jb⌋⌊kc⌋[gcd(i,j)=1][gcd(j,k)=1][gcd(i,k)=1]
将一个 [ g c d = 1 ] [gcd=1] [gcd=1]换掉(这里选择 ( i , j ) (i,j) (i,j),实际选哪个无区别)
= ∑ i = 1 a ∑ j = 1 b ∑ k = 1 c ⌊ a i ⌋ ⌊ b j ⌋ ⌊ c k ⌋ ∑ d ∣ g c d ( i , j ) μ ( d ) [ g c d ( j , k ) = 1 ] [ g c d ( i , k ) = 1 ] =\sum_{i=1}^a\sum_{j=1}^b\sum_{k=1}^c\left \lfloor \frac{a}{i} \right \rfloor\left \lfloor \frac{b}{j} \right \rfloor\left \lfloor \frac{c}{k} \right \rfloor\sum{_{d|gcd(i,j)}\mu(d)}[gcd(j,k)=1][gcd(i,k)=1] =∑i=1a∑j=1b∑k=1c⌊ia⌋⌊jb⌋⌊kc⌋∑d∣gcd(i,j)μ(d)[gcd(j,k)=1][gcd(i,k)=1]
= ∑ k = 1 c ⌊ c k ⌋ ∑ i = 1 a ⌊ a i ⌋ ∑ j = 1 b ⌊ b j ⌋ ∑ d ∣ g c d ( i , j ) μ ( d ) [ g c d ( j , k ) = 1 ] [ g c d ( i , k ) = 1 ] =\sum_{k=1}^c\left \lfloor \frac{c}{k} \right \rfloor\sum_{i=1}^a\left \lfloor \frac{a}{i} \right \rfloor\sum_{j=1}^b\left \lfloor \frac{b}{j} \right \rfloor\sum{_{d|gcd(i,j)}\mu(d)}[gcd(j,k)=1][gcd(i,k)=1] =∑k=1c⌊kc⌋∑i=1a⌊ia⌋∑j=1b⌊jb⌋∑d∣gcd(i,j)μ(d)[gcd(j,k)=1][gcd(i,k)=1]
枚举d,得(此时 a , b a,b a,b分别由 i d , j k id,jk id,jk构成,后面限制 k ⊥ i , j k\perp i,j k⊥i,j,要总体满足 a b c abc abc互质,还需限制 k ⊥ d k\perp d k⊥d)
= ∑ k = 1 c ⌊ c k ⌋ ∑ d = 1 m i n ( a , b ) μ ( d ) [ g c d ( k , d ) = 1 ] ∑ i = 1 ⌊ a d ⌋ ⌊ a i d ⌋ [ g c d ( i , k ) = 1 ] ∑ j = 1 ⌊ b d ⌋ b ⌊ b j d ⌋ [ g c d ( j , k ) = 1 ] =\sum_{k=1}^c\left \lfloor \frac{c}{k} \right \rfloor\sum_{d=1}^{min(a,b)}\mu(d)[gcd(k,d)=1]\sum_{i=1}^{\left \lfloor \frac{a}{d} \right \rfloor}\left \lfloor \frac{a}{id} \right \rfloor[gcd(i,k)=1]\sum_{j=1}^{\left \lfloor \frac{b}{d} \right \rfloor}b\left \lfloor \frac{b}{jd} \right \rfloor[gcd(j,k)=1] =∑k=1c⌊kc⌋∑d=1min(a,b)μ(d)[gcd(k,d)=1]∑i=1⌊da⌋⌊ida⌋[gcd(i,k)=1]∑j=1⌊db⌋b⌊jdb⌋[gcd(j,k)=1]
设 f ( x , y ) = ∑ i = 1 x ⌊ x i ⌋ [ g c d ( i , y ) = 1 ] f(x,y)=\sum_{i=1}^x\left \lfloor \frac{x}{i} \right \rfloor[gcd(i,y)=1] f(x,y)=∑i=1x⌊ix⌋[gcd(i,y)=1],得
= ∑ k = 1 c ⌊ c k ⌋ ∑ d = 1 m i n ( a , b ) μ ( d ) [ g c d ( k , d ) = 1 ] f ( ⌊ a d ⌋ , k ) f ( ⌊ b d ⌋ , k ) =\sum_{k=1}^c\left \lfloor \frac{c}{k} \right \rfloor\sum_{d=1}^{min(a,b)}\mu(d)[gcd(k,d)=1]f(\left \lfloor \frac{a}{d} \right \rfloor,k)f(\left \lfloor \frac{b}{d} \right \rfloor,k) =∑k=1c⌊kc⌋∑d=1min(a,b)μ(d)[gcd(k,d)=1]f(⌊da⌋,k)f(⌊db⌋,k)
f f f可 o ( n ) o(n) o(n)求出,可对gcd预处理打表减少求gcd花费的时间
int gcd[MAX_N][MAX_N];
int f[MAX_N][MAX_N];
int cal(int n,int m)
{
if(~f[n][m]) return f[n][m];//也可以不记忆化,而是第二个循环
int res=0;
repi(i,1,n)if(gcd[i][m]==1) res+=n/i;
return f[n][m]=res;
}
int main()
{
Moblus();
repi(i,1,2000)repi(j,i,2000) gcd[i][j]=gcd[j][i]=__gcd(i,j);
memset(f,-1,sizeof(f));
int a,b,c; si(a),si(b),si(c);
int ans=0;
repi(i,1,a)repi(j,1,min(b,c))if(gcd[i][j]==1) ans=(1ll*ans+mu[j]*(a/i)*cal(b/j,i)*cal(c/j,i)%mod)%mod;
printf("%d\n",(ans%mod+mod)%mod);
return 0;
}
10.P2257
设 P P P为质数,求 ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = P ] \sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=P] ∑i=1n∑j=1m[gcd(i,j)=P]
枚举 g c d gcd gcd,并对 [ g c d = 1 ] [gcd=1] [gcd=1]替换,得(设 n < m n
= ∑ p ∈ P ∑ d = 1 ⌊ n p ⌋ μ ( d ) ⌊ n p d ⌋ ⌊ m p d ⌋ =\sum_{p\in P}\sum_{d=1}^{\left \lfloor \frac{n}{p} \right \rfloor}\mu(d)\left \lfloor \frac{n}{pd} \right \rfloor\left \lfloor \frac{m}{pd} \right \rfloor =∑p∈P∑d=1⌊pn⌋μ(d)⌊pdn⌋⌊pdm⌋
设 T = p d T=pd T=pd,枚举 T T T
= ∑ T = 1 n ∑ p ∣ T ∩ p ∈ P μ ( T p ) ⌊ n T ⌋ ⌊ m T ⌋ =\sum_{T=1}^n\sum_{p|T \cap p\in P}\mu(\frac{T}{p})\left \lfloor \frac{n}{T} \right \rfloor\left \lfloor \frac{m}{T} \right \rfloor =∑T=1n∑p∣T∩p∈Pμ(pT)⌊Tn⌋⌊Tm⌋
设 g ( n ) = ∑ p ∣ n ∩ p ∈ P μ ( n p ) g(n)=\sum_{p|n \cap p\in P}\mu(\frac{n}{p}) g(n)=∑p∣n∩p∈Pμ(pn)
= ∑ T = 1 n g ( T ) ⌊ n T ⌋ ⌊ m T ⌋ =\sum_{T=1}^ng(T)\left \lfloor \frac{n}{T} \right \rfloor\left \lfloor \frac{m}{T} \right \rfloor =∑T=1ng(T)⌊Tn⌋⌊Tm⌋
对于 g g g,可以枚举每个质数,将其倍数的贡献计入,对每个数贡献累入倍数的均摊复杂度为 o ( l o g n ) o(logn) o(logn), 1 − n 1-n 1−n质数约 n l n ( n ) \frac {n}{ln(n)} ln(n)n个,总体复杂度约 o ( n ) o(n) o(n)
外层分块处理即可
ll g[MAX_N],sum_g[MAX_N];
ll solve(int n,int m)
{
if(n<m) swap(n,m);
ll ans=0;
for(int l=1,r;l<=m;l=r+1){
r=min(n/(n/l),m/(m/l));
ans+=(sum_g[r]-sum_g[l-1])*(n/l)*(m/l);
}
return ans;
}
int main()
{
Moblus();
repi(i,1,cntp)for(int j=1;1ll*j*prime[i]<MAX_N;j++) g[j*prime[i]]+=mu[j];
repi(i,1,MAX_N-1) sum_g[i]=sum_g[i-1]+g[i];
int T; si(T);
while(T--)
{
int n,m; si(n),si(m);
printf("%lld\n",solve(n,m));
}
return 0;
}
对 g g g函数,也可以在线性筛的时候处理(从莫比乌斯函数性质出发分析一下)
void Moblus()
{
repi(i,2,MAX_N-1) is_prime[i]=true; mu[1]=1;
repi(i,2,MAX_N-1){
if(is_prime[i]) prime[++cntp]=i*1ll,mu[i]=-1,g[i]=1;
repi(j,1,cntp){
if(i*prime[j]>MAX_N) break;
is_prime[i*prime[j]]=false;
if(i%prime[j]==0){
mu[i*prime[j]]=0,g[i*prime[j]]=mu[i];
break;
}
else mu[i*prime[j]]=-mu[i],g[i*prime[j]]=mu[i]-g[i];
}
}
}
不想把做的都再敲一遍证明了markdown打数学公式太累了
在留几个题吧,可以练习一下
P1447 hdu4746 hdu4575 bzoj3529
完结撒花~