Lucas的数论题解

Lucas的数论

reference

题目在这里> <

Pre

数论分块

默认向下取整时.

形如\(\sum\limits_{i=1}^n f\left( \frac{n}{i}\right)\)的求和,由于\(\frac{n}{r}\)的值只有\(\sqrt{n}\)个,可以直接数论分块上.

题解

记原式为\(S(n)\),有

\[S(n)=\sum_{i\rightarrow n}\sum_{j\rightarrow n}[\gcd{i,j}=1]\frac{n}{i}\frac{n}{j} \]

\[=\sum_k\mu (k)\sum_{i\rightarrow\frac{n}{k}}\sum_{d\rightarrow\frac{n}{k}}\frac{n}{ik}\frac{n}{dk} \]

\[F(n)=\sum_{i\rightarrow n}d(i) \]

\[S(n)=\sum_k\mu(k)F\left(\frac{n}{k}\right) ^2 \]

那么

\[F(n)=\sum_{j=1}^n\lfloor \frac{n}{j}\rfloor \]

可以直接上数论分块.
那么$$S(n)$$也可以数论分块球了> <...
然后\(\mu\)函数的前缀和...就这样:

然后发现也可以数论分块+记忆化搜索搞一搞.

然后就莫名其妙地过了> <

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <ext/rope>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/priority_queue.hpp>
#define fon(i,n) for(int i=0;i<n;++i)
#define fonx(i,f,n,s) for(int i=f;i<n;i+=s)
#define fonu(i,n) for(int i=1;i<n;i<<=1)
#define fong(i,s,n) for(int i=s;i<=n;++i)
#define debug true
#define pi 3.14159265358979323846264
#define mod 1000000007
typedef long long ll;
typedef unsigned long long ull;

struct __sieve{
	int primes[1000000],primelen,spf[5000000+1],lm[5000000+1];
	bool isk[5000000+1];
	int lmer[5000000+1];
	void operator()(){
		lmer[1]=lm[1]=1;
		fong(i,2,5000000){
			if(!isk[i]) lm[i]=-1,primes[primelen++]=i;
			fon(j,primelen){
				int k=i*primes[j];
				if(k>5000000) break;
				isk[k]=1;
				if(i%primes[j]) lm[k]=-lm[i]; else {
					lm[k]=0;
					break;
				}
			}
			lmer[i]=lmer[i-1]+lm[i];
		}
	}
	inline int operator[](int a){return lmer[a];}
} linear_sieve;

struct __hash{
	#define hashmod 3001001
	inline int hash(int n){
		return ((n*405347)&1073741823)%hashmod;
	}
	int n[hashmod][3],h[hashmod],len;
	inline int find(int N){
		int p=hash(N);
		int q=h[p];
		while(p&&n[p][0]!=N) p=n[p][2];
		return p?n[p][1]:-1;
	}
	inline void ins(int N,int p){
		++len;
		int q=hash(N);
		n[len][0]=N,n[len][1]=p,n[len][2]=h[q],h[q]=len;
	}
} hashmap;
int N,n;

int sumMiu(int a){
	if(a<=5000000) return linear_sieve[a];
	int res=hashmap.find(a);
	if(~res) return res;
	int t=1;
	for (int l = 1, r = 2,n=a; r <= n; r ++){
		r = std::min(n, n / (n / r));
		int tmp = n / r;
		t-=(r-l+mod)%mod*sumMiu(tmp)%mod;
		t=(r<0)?t+mod:t;
		l = r;
	}
	hashmap.ins(a,t);
	return t;
}

int F(int n){
	int ans = 0;
	for (int l = 0, r = 1; r <= n; r ++){
		r = std::min(n, n / (n / r));
		int res = (n / r) % mod;
		int tmp = (r - l + mod) % mod * res % mod;
		ans += tmp;
		if (ans >= mod) ans -= mod;
		l = r;
	}
	return ans;
}

int main(){
#ifdef debug
	freopen("mathP.in","r",stdin);
	freopen("mathP.out","w",stdout);
#endif
	scanf("%d",&n);
	N=(int)pow((double)n,.5);
	linear_sieve();
	int ans=0;
	for (int l = 0, r = 1; r <= n; r ++){
		r = std::min(n, n / (n / r));
		int res=F(n/r);
		ans+=((ll)sumMiu(r)-sumMiu(l)+mod)%mod*res%mod*res%mod;
		if(ans>=mod) ans-=mod;
		l = r;
	}
	printf("%d\n",ans);
	return 0;
}
posted @ 2015-07-08 20:06  zball  阅读(231)  评论(0编辑  收藏  举报