码迷,mamicode.com
首页 > 其他好文 > 详细

●HDU 5608 function

时间:2018-01-19 14:19:53      阅读:122      评论:0      收藏:0      [点我收藏+]

标签:void   c++   复杂度   $$   bit   复杂   post   prim   def   

题链:

http://acm.hdu.edu.cn/showproblem.php?pid=5608

题解:

莫比乌斯反演,杜教筛

已知$$N^2-3N+2=\sum_{d|N} f(d)$$

多次询问,给出n,求f的前缀和S(n)。

 


 

把f函数卷上$I(x)=1$

那么有:

$$\sum_{i=1}^{n}f*l(i)=\sum_{i=1}^{n}l(i)S(\lfloor \frac{n}{i} \rfloor)$$

所以:

$$S(n)=\sum_{i=1}^{n}f*l(i)-\sum_{i=2}^{n}S(\lfloor \frac{n}{i} \rfloor)$$

又因为

$$\begin{aligned}
\sum_{i=1}^{n}f*l(i)&=\sum_{i=1}^{n}\sum_{d|i}f(d)l(\frac{i}{d})\\
&=\sum_{i=1}^{n}\sum_{d|i}f(d)\\
&=\sum_{i=1}^{n}(i^2-3i+2)\\
&=\frac{n(n+1)(2n+1)}{6}-\frac{3n(1+n)}{2}+2n\\
\end{aligned}$$

所以

$$S(n)=\frac{n(n+1)(2n+1)}{6}-\frac{3n(1+n)}{2}+2n-\sum_{i=2}^{n}S(\lfloor \frac{n}{i} \rfloor)$$

到此,就可以直接用杜教筛求解了,不过有点慢。


我们可以先预处理出前$n^{\frac{2}{3}}$个的前缀和

令$F(N)=N^2-3N+2$,那么F就是f的约数和函数

(因为$F(N)=\sum_{d|N}f(d)$

所以由莫比乌斯反演可知:

$$f(N)=\sum_{d|N}\mu(d)F(\frac{N}{d})$$

然后可以用$O(nlogn)$的复杂度先处理出一些前缀和,

然后再杜教筛即可。

代码:

#include<bits/stdc++.h>
#define DJM 1000000
using namespace std;
const int mod=1000000007;
struct Hash_Table{
	#define Hmod 1425367
	int org[DJM+50],val[DJM+50],nxt[DJM+50],head[Hmod],hnt;
	Hash_Table(){hnt=1;}
	void Push(int x,int v){
		static int u; u=x%Hmod; 
		org[hnt]=x; val[hnt]=v; nxt[hnt]=head[u]; head[u]=hnt++;
	}
	int Find(int x){
		static int u; u=x%Hmod;
		for(int i=head[u];i;i=nxt[i])
			if(org[i]==x) return val[i];
		return -1;
	}
}H;
int mu[DJM+50],F[DJM+50],f[DJM+50];
void Sieve(){
	static bool np[DJM+50];
	static int prime[DJM+50],pnt;
	mu[1]=1;
	for(int i=2;i<=DJM;i++){
		F[i]=(1ll*i*i-3*i+2+mod)%mod;
		if(!np[i]) prime[++pnt]=i,mu[i]=-1;
		for(int j=1;j<=pnt&&i<=DJM/prime[j];j++){
			np[i*prime[j]]=1;
			if(i%prime[j]) mu[i*prime[j]]=-mu[i];
			else break;
		}
	}
	for(int d=1;d<=DJM;d++)
		for(int i=1;i*d<=DJM;i++)
			f[i*d]=(1ll*f[i*d]+1ll*mu[d]*F[i]%mod+mod)%mod;
	for(int i=1;i<=DJM;i++) f[i]=(1ll*f[i]+f[i-1])%mod;
}
int DJ_pf(int n){
	static int inv6=166666668;
	if(n<=DJM) return f[n];
	if(H.Find(n)!=-1) return H.Find(n);
	int ret=(1ll*n*(n+1)%mod*(2*n+1)%mod*inv6%mod-3ll*(1+n)*n/2%mod+2ll*n%mod+mod)%mod;
	for(int i=2,last;i<=n;i=last+1){
		last=n/(n/i);
		ret=(1ll*ret-1ll*(last-i+1)*DJ_pf(n/i)%mod+mod)%mod;
	}
	H.Push(n,ret);
	return ret;
}
int main(){
	Sieve(); int Case,n;
	for(scanf("%d",&Case);Case;Case--){
		scanf("%d",&n);
		printf("%d\n",DJ_pf(n));
	}
	return 0;
}

  

●HDU 5608 function

标签:void   c++   复杂度   $$   bit   复杂   post   prim   def   

原文地址:https://www.cnblogs.com/zj75211/p/8316203.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!