杜教筛板子

Posted uid001

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了杜教筛板子相关的知识,希望对你有一定的参考价值。

杜教筛核心公式

$g(1)S(n)=\sum\limits_i=1^n(f*g)(i)-\sum\limits_i=2^n g(i)S(\lfloor \fracni\rfloor)$

$S$是需要求的$f$的前缀和, $g$是构造的一个函数

$g$需要满足$g$和$f*g$的前缀和可以$O(1)$求出

$N$是最大范围, $N2$是$N^2/3$, $N3$是$N^1/3$.

$N$范围超过$int$时要在$map$和$sum$里改成$ll$

多组数据时, 只需要最开始调用一次init, 之后每组数据map不用清零

const int N2 = 5e6+10;
int cnt,f[N2],p[N2],vis[N2];
map<int,int> S2;
void init() 
    f[1] = 1;
    REP(i,2,N2-1) 
        if (!vis[i]) p[++cnt]=i,f[i] = ((ll)i*i-1)%P;
        for (int j=1,t;j<=cnt&&i*p[j]<N2; ++j) 
            vis[t=i*p[j]] = 1;
            if (i%p[j]==0) f[t]=(ll)f[i]*p[j]%P*p[j]%P;break;
            f[t] = (ll)f[i]*f[p[j]]%P;
        
    
	REP(i,2,N2-1) f[i] = (f[i]+f[i-1])%P;

int g(int n) return 1;
int sum_g(int n) return n;
int sum_fg(int n) return (ll)n*(n+1)%P*(2*n+1)%P*inv6%P;

int sum(int n) 
    if (n<N2) return f[n];
    if (S2.count(n)) return S2[n];
    int ans = sum_fg(n), mx = sqrt(n);
    REP(i,2,mx) ans=(ans-(ll)g(i)*sum(n/i))%P;
    for (int i=mx+1,j,k=n/i; i<=n; i=j+1,--k) 
        j = n/k;
        ans = (ans-(ll)(sum_g(j)-sum_g(i-1))*sum(k))%P;
    
    return S2[n]=ans;


void init() 
    f[1] = 1;
    REP(i,2,N2-1) 
        if (!vis[i]) p[++cnt]=i, f[i] = 1;
        for (int j=1,t;j<=cnt&&i*p[j]<N2; ++j) 
            vis[t=i*p[j]] = 1;
            if (i%p[j]==0) f[t] = 1;break;
            f[t] = (ll)f[i]*f[p[j]]%P;
        
    
	REP(i,2,N2-1) f[i] = (f[i]+f[i-1])%P;

int sum(int n) 
    if (n<N2) return f[n];
    if (S2.count(n)) return S2[n];
    int ans = sum_fg(n), mx = sqrt(n);
    REP(i,2,mx) ans=(ans-(ll)g(i)*sum(n/i))%P;
    for (int i=mx+1,j,k=n/i; i<=n; i=j+1,--k) 
		j = n/k;
		ans = (ans-(ll)(sum_g(j)-sum_g(i-1))*sum(k))%P;
    
	if (ans<0) ans += P;
    return S2[n]=ans;

不用map的写法, 这样需要每组数据把$v$用时间戳清零.

const int N2 = 5e6+10;
const int N3 = 2510;
int clk,cnt,f[N2],p[N2],vis[N2];
int S2[N3], v[N3];
void init() 
    f[1] = 1;
    REP(i,2,N2-1) 
        if (!vis[i]) p[++cnt]=i, f[i] = 1;
        for (int j=1,t;j<=cnt&&i*p[j]<N2; ++j) 
            vis[t=i*p[j]] = 1;
            if (i%p[j]==0) f[t] = 1;break;
            f[t] = (ll)f[i]*f[p[j]]%P;
        
    
	REP(i,2,N2-1) f[i] = (f[i]+f[i-1])%P;

int sum(int n) 
    if (n<N2) return f[n];
	int x = N/n;
	if (v[x]==clk) return S2[x];
	v[x] = clk;
	int &ans = S2[x] = sum_fg(n), mx = sqrt(n);
    REP(i,2,mx) ans=(ans-(ll)g(i)*sum(n/i))%P;
    for (int i=mx+1,j,k=n/i; i<=n; i=j+1,--k) 
		j = n/k;
		ans = (ans-(ll)(sum_g(j)-sum_g(i-1))*sum(k))%P;
    
	if (ans<0) ans += P;
    return ans;

 

以上是关于杜教筛板子的主要内容,如果未能解决你的问题,请参考以下文章

51nod 1220 约数之和(杜教筛 + 推推推推推公式)

杜教筛题表(已完成)

杜教筛学习笔记

hdu5608杜教筛

杜教筛

杜教筛