51Nod1220 约数之和 【杜教筛】

版权声明:本文为博主原创文章,未经博主允许必须转载。 https://blog.csdn.net/C20181220_xiang_m_y/article/details/85038010

题目描述:

i = 1 n j = 1 n σ 1 ( i j ) \sum_{i=1}^n\sum_{j=1}^n\sigma_1(i*j)
n 1 0 9 m o d   1 0 9 + 7 n\le10^9,mod ~10^9+7

题目分析:

有个结论: σ k ( i j ) = x i y j [ ( x , y ) = = 1 ]   x k j k / y k \sigma_k(i*j)=\sum_{x|i}\sum_{y|j}[(x,y)==1]~x^k*j^k/y^k
σ k ( n ) \sigma_k(n) n n 的约数的 k k 次幂之和,质因数分解 n n n = p 1 a 1 p 2 a 2 . . . p t a t n=p_1^{a_1}p_2^{a_2}...p_t^{a_t}
σ k ( n ) = ( 1 + p 1 1 k + p 1 2 k + + p 1 a 1 k )             ( 1 + p 2 1 k + p 2 2 k + + p 2 a 2 k )                         ( 1 + p t 1 k + p t 2 k + + p t a t k ) \sigma_k(n)=(1+p_1^{1k}+p_1^{2k}+\dots+p_1^{a_1k})\\~~~~~~~~~~~*(1+p_2^{1k}+p_2^{2k}+\dots+p_2^{a_2k})\\~~~~~~~~~~~~\dots\\~~~~~~~~~~*(1+p_t^{1k}+p_t^{2k}+\dots+p_t^{a_tk})
考虑一个质因子 p p ,它对 σ k ( n ) \sigma_k(n) 的贡献为 1 + p k + p 2 k + . . . + p a k 1+p^k+p^{2k}+...+p^{ak}
那么看 σ k ( i j ) \sigma_k(i*j) ,考虑它们的公共质因子 p p ,在i中有a次,在j中有b次,造成的贡献就可以表示为 x = 0 a y = 0 b [ ( p x , p y ) = = 1 ]   p x k p b k / p y k \sum_{x=0}^a\sum_{y=0}^b[(p^x,p^y)==1]~p^{xk}*p^{bk}/p^{yk}
根据乘法原理,有 σ k ( i j ) = x 1 = 0 a 1 y 1 = 0 b 1 [ ( p x 1 , p y 1 ) = = 1 ]   p x 1 k p b 1 k / p y 1 k                 x 2 = 0 a 2 y 2 = 0 b 2 [ ( p x 2 , p y 2 ) = = 1 ]   p x 2 k p b 2 k / p y 2 k                 x t = 0 a t y t = 0 b t [ ( p x t , p y t ) = = 1 ]   p x t k p b t k / p y t k \sigma_k(i*j)=\sum_{x_1=0}^{a_1}\sum_{y_1=0}^{b_1}[(p^{x_1},p^{y_1})==1]~p^{x_1k}*p^{b_1k}/p^{y_1k}\\~~~~~~~~~~~~~~~* \sum_{x_2=0}^{a_2}\sum_{y_2=0}^{b_2}[(p^{x_2},p^{y_2})==1]~p^{x_2k}*p^{b_2k}/p^{y_2k}\\\dots\\ ~~~~~~~~~~~~~~~*\sum_{x_t=0}^{a_t}\sum_{y_t=0}^{b_t}[(p^{x_t},p^{y_t})==1]~p^{x_tk}*p^{b_tk}/p^{y_tk}
只有当所有 ( p x , p y ) = = 1 (p^x,p^y)==1 都满足时才会对答案造成贡献,所以可变形为:
σ k ( i j ) = x i y j [ ( x , y ) = = 1 ]   x k j k / y k \sigma_k(i*j)=\sum_{x|i}\sum_{y|j}[(x,y)==1]~x^k*j^k/y^k

ok,正文开始

i = 1 n j = 1 n σ 1 ( i j ) = i = 1 n j = 1 n x i y j [ ( x , y ) = = 1 ]   x j / y = k = 1 n μ ( k ) x = 1 n k n k x y = 1 n k j = 1 n k y x k k y j / k y = k = 1 n μ ( k ) k x = 1 n k n k x x j = 1 n k j n k j = k = 1 n μ ( k ) k ( x = 1 n k n k x x ) 2 = k = 1 n μ ( k ) k ( i = 1 n k σ 1 ( i ) ) 2 \large\begin{aligned} &\sum_{i=1}^n\sum_{j=1}^n\sigma_1(i*j)\\ &=\sum_{i=1}^n\sum_{j=1}^n\sum_{x|i}\sum_{y|j}[(x,y)==1]~x*j/y\\ &=\sum_{k=1}^n\mu(k)\sum_{x=1}^{\frac nk}\lfloor\frac n{kx}\rfloor\sum_{y=1}^{\frac nk}\sum_{j=1}^{\frac n{ky}}xk*kyj/ky\\ &=\sum_{k=1}^n\mu(k)k\sum_{x=1}^{\frac nk}\lfloor\frac n{kx}\rfloor x\sum_{j=1}^{\frac nk}j\lfloor\frac n{kj}\rfloor\\ &=\sum_{k=1}^n\mu(k)k\left(\sum_{x=1}^{\frac nk}\lfloor\frac n{kx}\rfloor x\right)^2\\ &=\sum_{k=1}^n\mu(k)k\left(\sum_{i=1}^{\frac nk}\sigma_1(i)\right)^2 \end{aligned}

线性筛 1 0 6 10^6 μ ( k ) k \mu(k)k 标准的杜教筛, σ 1 ( n ) n \sigma_1(n)的前缀和可以\sqrt n 分块暴算
时间复杂度 O ( n 2 3 ) O(n^{\frac 23})

  • 其实有种更简单清晰的推法,第一步先不要把x,y提到最前面
    = i = 1 n j = 1 n x i y j [ ( x , y ) = = 1 ]   x j / y = k = 1 n μ ( k ) i = 1 n k j = 1 n k x i y i x k j k / y k = k = 1 n μ ( k ) k i = 1 n k j = 1 n k x i x y j j y = k = 1 n μ ( k ) k i = 1 n k j = 1 n k σ 1 ( i ) σ 1 ( j ) = k = 1 n μ ( k ) k ( i = 1 n k σ 1 ( i ) ) 2 \begin{aligned} &=\sum_{i=1}^n\sum_{j=1}^n\sum_{x|i}\sum_{y|j}[(x,y)==1]~x*j/y\\ &=\sum_{k=1}^n\mu(k)\sum_{i=1}^{\frac nk}\sum_{j=1}^{\frac nk}\sum_{x|i}\sum_{y|i}xk*jk/yk\\ &=\sum_{k=1}^n\mu(k)k\sum_{i=1}^{\frac nk}\sum_{j=1}^{\frac nk}\sum_{x|i}x\sum_{y|j}{\frac jy}\\ &=\sum_{k=1}^n\mu(k)k\sum_{i=1}^{\frac nk}\sum_{j=1}^{\frac nk}\sigma_1(i)*\sigma_1(j)\\ &=\sum_{k=1}^n\mu(k)k\left(\sum_{i=1}^{\frac nk}\sigma_1(i)\right)^2 \end{aligned}
#include<cstdio>
#include<map>
using namespace std;
const int N = 1000000, mod = 1e9+7, inv2 = 5e8+4;
int p[N/10],sm[N+5],sd[N+5],mp[N+5];
bool v[N+5];
map<int,int>F;
void Prime()
{
	sm[1]=sd[1]=1;int cnt=0;
	for(int i=2;i<=N;i++)
	{
		if(!v[i]) p[++cnt]=i,sm[i]=-i,sd[i]=mp[i]=i+1;
		for(int j=1,k;j<=cnt&&(k=p[j]*i)<=N;j++)
		{
			v[k]=1;
			if(i%p[j]==0) {sm[k]=0,mp[k]=mp[i]*p[j]+1,sd[k]=sd[i]/mp[i]*mp[k];break;}
			sm[k]=sm[i]*sm[p[j]];
			sd[k]=sd[i]*sd[p[j]];
			mp[k]=p[j]+1;
		}
	}
	for(int i=1;i<=N;i++) sm[i]=(sm[i]+sm[i-1])%mod,sd[i]=(sd[i]+sd[i-1])%mod;
}
int Summu(int n)
{
	if(n<=N) return sm[n];
	if(F.count(n)) return F[n];
	int ret=1;
	for(int i=2,j;i<=n;i=j+1)
	{
		j=n/(n/i);
		ret=(ret-1ll*(i+j)*(j-i+1)%mod*inv2%mod*Summu(n/i))%mod;
	}
	return F[n]=ret;
}
int calc(int n)
{
	if(n<=N) return sd[n];
	int ret=0;
	for(int i=1,j;i<=n;i=j+1)
	{
		j=n/(n/i);
		ret=(ret-1ll*(i+j)*(j-i+1)%mod*inv2%mod*(n/i))%mod;
	}
	return ret;
}
int main()
{
	Prime();
	int n,ans=0;
	scanf("%d",&n);
	for(int i=1,j,tmp,pre=0,tt;i<=n;i=j+1)
	{
		j=n/(n/i);
		ans=(ans+1ll*((tmp=Summu(j))-pre)*(tt=calc(n/i))%mod*tt)%mod;
		pre=tmp;
	}
	printf("%d",(ans+mod)%mod);
}

猜你喜欢

转载自blog.csdn.net/C20181220_xiang_m_y/article/details/85038010
今日推荐