P3708 koishi的数学题(因数和)

Posted Harris-H

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P3708 koishi的数学题(因数和)相关的知识,希望对你有一定的参考价值。

P3708 koishi的数学题(因数和)

题目传送门

值得学习的点

  • 因子和 σ ( n ) = ∑ d ∣ n d \\sigma(n)=\\sum\\limits_{d|n}d σ(n)=dnd
  • x ( m o d y ) = x − ⌊ x y ⌋ × y x\\pmod y = x - \\lfloor\\dfrac{x}{y}\\rfloor \\times y x(mody)=xyx×y

f ( x ) = ∑ i = 1 n x ( m o d i ) f(x)=\\sum\\limits_{i=1}^n x\\pmod{i} f(x)=i=1nx(modi),求 f ( 1 ) , f ( 2 ) … , f ( n ) f(1),f(2)\\dots,f(n) f(1),f(2),f(n)

考虑递推的关系

f ( x ) = ∑ i = 1 n x ( m o d i ) = n x − ∑ i = 1 n ( ⌊ x i ⌋ × i ) f(x)=\\sum\\limits_{i=1}^n x\\pmod {i}=nx-\\sum\\limits_{i=1}^n (\\lfloor\\dfrac{x}{i}\\rfloor \\times i) f(x)=i=1nx(modi)=nxi=1n(ix×i)

f ( x ) − f ( x − 1 ) = n − ∑ i = 1 n i ( ⌊ x i ⌋ − ⌊ x − 1 i ⌋ ) f(x)-f(x-1)=n-\\sum\\limits\\limits_{i=1}^n i(\\lfloor\\dfrac{x}{i}\\rfloor-\\lfloor\\dfrac{x-1}{i}\\rfloor ) f(x)f(x1)=ni=1ni(ixix1)

i ∣ x i|x ix时, ( ⌊ x i ⌋ − ⌊ x − 1 i ⌋ ) = 1 (\\lfloor\\dfrac{x}{i}\\rfloor-\\lfloor\\dfrac{x-1}{i}\\rfloor )=1 (ixix1)=1

否则等0。

所以 ∑ i = 1 n i ( ⌊ x i ⌋ − ⌊ x − 1 i ⌋ ) = ∑ d ∣ x x d = σ ( x ) \\sum\\limits\\limits_{i=1}^ni(\\lfloor\\dfrac{x}{i}\\rfloor-\\lfloor\\dfrac{x-1}{i}\\rfloor )=\\sum\\limits_{d|x}^x d=\\sigma(x) i=1ni(ixix1)=dxxd=σ(x)

f ( x ) − f ( x − 1 ) = n − σ ( x ) f(x)-f(x-1)=n-\\sigma(x) f(x)f(x1)=nσ(x)

预处理 σ ( i ) \\sigma(i) σ(i),然后 O ( n ) O(n) O(n)递推。

预处理 σ ( i ) \\sigma(i) σ(i)的两种方法:

  • 每个因数的对哪些数有贡献 O ( n l o g n ) O(nlogn) O(nlogn)
  • 线性筛 O ( n ) O(n) O(n)
//暴力筛O(nlogn)
ll f[N],s;
int n;
void init(int n){
	for(int i=1;i<=n;i++)	
		for(int j=i;j<=n;j+=i) f[j]+=i;
}
//线筛O(n)
ll f[N],s,g[N];
int p[N],cnt,vis[N];
int n;
void init(int n){
	vis[0]=vis[1]=1;
	f[1]=1;
	for(int i=2;i<=n;i++){
		if(!vis[i]) p[++cnt]=i,f[i]=g[i]=i+1;
		for(int j=1;j<=cnt&&i*p[j]<=n;j++){
			vis[i*p[j]]=1;
			if(i%p[j]==0){
				g[i*p[j]]=g[i]*p[j]+1;
				f[i*p[j]]=f[i]/g[i]*g[i*p[j]];
				break;
			}
			f[i*p[j]]=f[i]*f[p[j]];
			g[i*p[j]]=g[p[j]];
		}
	}
}

因数和线筛的证明

自己来证明下 O ( n ) O(n) O(n)的线筛:

前置知识: