Min_25筛

  • \(\sum\limits_{i=1}^{n}f(i)\)其中\(f\)为积性函数。
  • 我们先把烦人的\(1\)踢掉,接下来都从\(2\)开始枚举,显然\(f(1)=1\)
  • \(P_x\)为第\(x\)个质数,\(mn_x\)\(x\)的最小质因子。
  • \(s_{x,y}=\sum\limits_{2\le i\le x,mn_i\ge P_y}f(i)\)
  • \(g_{n,m}=\sum\limits_{2\le x\le n,is[x]\ or\ mn_x>P_m}f(x)\)
  • \(g_{n,m}=g_{n,m-1}(P_m^2>n)\)
  • \(g_{n,m}=g_{n,m-1}-f(P_m)\times [g_{n/P_m,m-1}-\sum\limits_{i=1}^{m-1}f(P_i)]\ (P_m^2\le n)\)
  • 实现 : 对第二维滚动。
  • 如何处理第一维?
  • 回到刚才,求\(s_{x,y}\)
  • \(s_{x,y}=\sum\limits_{2\le i\le x,is[i],mn_i\ge P_y}f(i)+\sum\limits_{2\le i\le x,!is[i],mn_i\ge P_y}f(i)\)
  • \(s_{x,y}=g_{x,\infty}-\sum\limits_{i=1}^{y-1}f(P_i)+\sum\limits_{y\le p\le \sqrt x,is[p],e\ge 1,p^{e+1}\le x}f(P_p^e)\times s_{x/P_p^e,p+1}+\sum\limits_{2\le p\le \sqrt x,is[p],e\ge 2,p^e\le x}f(P_p^{e})\)
  • \(s_{x,y}=g_{x,\infty}-\sum\limits_{i=1}^{y-1}f(P_i)+\sum\limits_{y\le p\le \sqrt x,is[p],e\ge 1,p^{e+1}\le x}f(P_p^e)\times s_{x/P_p^e,p+1}+f(P_p^{e+1})\)
  • 这步需要递归下去,注意到需要的\(g\)的第一维是\(\lfloor \frac{n}{t}\rfloor\)形式的,最多\(\sqrt n\)个,离散化即可。
  • 目前不会证,先抄几个定理上来。
  • \(\sum\limits_{p\ge n,is[p]}=\Theta(\frac{1}{n\ln n})\)

SP34096 DIVCNTK

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
#include <cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
#define N 200050
int vis[N],cnt,id1[N],id2[N],tot;
ll n,w[N],pri[N];
ull g[N],K;
int S;
int pos(ll x) {return x<=S?id1[x]:id2[n/x];}
void sieve() {
    int i,j;
    for(i=2;i<N;i++) {
        if(!vis[i]) pri[++cnt]=i;
        for(j=1;j<=cnt&&i*pri[j]<N;j++) {
            vis[i*pri[j]]=1; if(i%pri[j]==0) break;
        }
    }
}
ull sf(int x) {return (K+1)*x;}
ull f(int x) {return (K+1);}
ull fp(int x,int e) {return K*e+1;}
ull get_s(ll x,int y) {
    if(x<=1||pri[y]>x) return 0;
    ull ans=g[pos(x)]-sf(y-1);
    int i,e;
    for(i=y;i<=cnt&&pri[i]*pri[i]<=x;i++) {
        ll t=pri[i], tt=t*t;
        for(e=1;tt<=x;e++,t=tt,tt*=pri[i]) {
            ans+=fp(i,e)*get_s(x/t,i+1)+fp(i,e+1);
        }
    }return ans;
}
int main() {
    sieve();
    int T;
    scanf("%d",&T);
    while(T--) {
        scanf("%lld%llu",&n,&K);
        S=sqrt(n); tot=0;
        ll i,lst,j;
        for(i=1;i<=n;i=lst+1) {
            lst=n/(n/i); ll t=n/i; w[++tot]=t; g[tot]=t-1;
            if(t<=S) id1[t]=tot; else id2[n/t]=tot;
        }
        for(i=1;pri[i]<=S;i++) {
            for(j=1;j<=tot&&w[j]>=pri[i]*pri[i];j++) {
                g[j]-=g[pos(w[j]/pri[i])]-(i-1);
            }
        }
        for(i=1;i<=tot;i++) g[i]*=(K+1);
        printf("%llu\n",get_s(n,1)+1);
        for(i=1;i<=tot;i++) w[i]=g[i]=0;
    }
}

LOJ#6053. 简单的函数

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
typedef long long ll;
#define N 200050
#define mod 1000000007
ll n,pri[N],w[N],g[N],h[N];
int S,cnt,tot,vis[N],id1[N],id2[N];
int pos(ll x) {return x<=S?id1[x]:id2[n/x];}
ll sum[N];
ll fp(int p,int e) {return (pri[p]^e)%mod;}
ll get_s(ll x,int y) {
	if(x<=1||pri[y]>x) return 0;
	ll ans=(g[pos(x)]-h[pos(x)]-(sum[y-1]-(y-1)))%mod;
	if(y==1) ans=(ans+2)%mod;
	int p,e;
	for(p=y;p<=cnt&&pri[p]*pri[p]<=x;p++) {
		ll t=pri[p],tt=t*t;
		for(e=1;tt<=x;e++,t=tt,tt*=pri[p]) {
			ans=(ans+fp(p,e)*get_s(x/t,p+1)+fp(p,e+1))%mod;
		}
	}
	return ans;
}
int main() {
	ll i,j;
	for(i=2;i<N;i++) {
		if(!vis[i]) pri[++cnt]=i;
		for(j=1;j<=cnt&&i*pri[j]<N;j++) {
			vis[i*pri[j]]=1; if(i%pri[j]==0) break;
		}
	}
	for(i=1;i<=cnt;i++) sum[i]=(sum[i-1]+pri[i])%mod;
	scanf("%lld",&n);
	ll lst;
	S=sqrt(n);
	for(i=1;i<=n;i=lst+1) {
		lst=n/(n/i);
		ll t=n/i; w[++tot]=t;
		if(t<=S) id1[t]=tot; else id2[n/t]=tot;
		g[tot]=(t+2)%(mod<<1)*((t-1)%(mod<<1))/2%mod; h[tot]=t-1;
	}
	for(i=1;pri[i]<=S;i++) {
		for(j=1;j<=tot&&w[j]>=pri[i]*pri[i];j++) {
			g[j]=(g[j]-pri[i]*(g[pos(w[j]/pri[i])]-sum[i-1]))%mod;
			h[j]=(h[j]-(h[pos(w[j]/pri[i])]-(i-1)))%mod;
		}
	}
	printf("%lld\n",(get_s(n,1)+1+mod)%mod);
}


**反正考了我也不会就不写非模板的题了。**
posted @ 2018-12-17 20:55  fcwww  阅读(223)  评论(0编辑  收藏  举报