zoukankan      html  css  js  c++  java
  • min25筛学习笔记

    min25筛简介:用来求积性函数F(x)前缀和的,复杂度O(n0.75/logn),大概能求n<=1010

    记一个数x的最小质因子为R(x),所以当x不为质数时,R(x)<=√x这是废话

    首先求所有质数的F(x)和,下设g(i,j)=ΣF(x),其中2<=x<=i,且x为质数或R(x)>pri[j],其中pri[j]为第j个质数。其实,j的取值至多√n个显而易见,下面可以发现最终状态是g(i,tot),其中tot为√n以内的质数个数。初始化g(i,0),即将所有数视为质数处理,然后将合数筛去,剩下的即为所要求的值。

    然后g的递推式也是显而易见,用g(i,j-1)推g(i,j),可以得到g(i,j)=g(i,j-1)-F(pri[j])*(g(i/pri[j],j-1)-sF(j-1)),其中sF(x)=ΣF(pri[i]),其中1<=i<=x。

    注:此时i/pri[j]可能会小于pri[j],但此时显然g(i,j)=g(i,j-1)

    第一维的大小只有2√n,显然应该离散存储。

    然后下面考虑求所有数的F(x)前缀和,此时类似g的定义设f(i,j)=ΣF(x),其中2<=x<=i,且x为质数或R(x)>=pri[j]。对于f(i,j)显然质数部分为g(i,tot)-sF(j-1),合数部分,枚举最小因子及其次幂pk使p>=pri[j],然后F函数实际上是F(pk)*f(i/pk,p的序号+1),不知道为啥,不需要记忆化。

    例题:LOJ6053

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=1e5+1000,mod=1e9+7,inv2=500000004;
    ll n,P,cnt,id1[N],id2[N],w[2*N],m,g[2*N],h[2*N],f[2*N],pri[N],pre[N],vis[N];
    void init()
    {
        for(int i=2;i<=1e5;++i)
        {
            if(!vis[i])pri[++cnt]=i,pre[cnt]=(pre[cnt-1]+i)%mod;
            for(int j=1;j<=cnt&&i*pri[j]<=1e5;++j)
            {
                vis[i*pri[j]]=1;
                if(i%pri[j]==0)break;
            }
        }
    }
    int getid(ll x){return x<=P?id1[x]:id2[n/x];}
    void calc()
    {
        ll v,r;
        for(ll l=1;l<=n;l=r+1)
        {
            v=n/l,r=n/v;
            if(v<=P)id1[v]=++m;else id2[r]=++m;
            w[m]=v;
            ll z=v%mod;
            g[m]=(z+2)*(z-1)%mod*inv2%mod;
            h[m]=z-1;
        }
        for(ll i=1;i<=cnt;++i)
        for(ll j=1;j<=m&&pri[i]*pri[i]<=w[j];++j)
        {
            int op=getid(w[j]/pri[i]);
            g[j]=(g[j]-pri[i]*(g[op]-pre[i-1])%mod)%mod;
            h[j]=(h[j]-(h[op]-i+1))%mod;
        }
        for(int i=1;i<=m;++i)g[i]=(g[i]+mod)%mod,f[i]=(f[i]+mod)%mod,f[i]=(g[i]-h[i])%mod;
    }
    ll ask(ll x,ll i)
    {
        if(x<=1||x<pri[i])return 0;
        ll ans=f[getid(x)]-(pre[i-1]-i+1);
        if(i==1)ans+=2;
        for(int j=i;j<=cnt&&pri[j]*pri[j]<=x;++j)
        {
            ll r=pri[j];
            for(ll e=1;r*pri[j]<=x;++e,r*=pri[j])
            ans=(ans+(pri[j]^e)*ask(x/r,j+1)+(pri[j]^(e+1)))%mod;
        }
        return ans;
    }
    int main()
    {
        cin>>n;P=sqrt(n);
        init();
        calc();
        printf("%lld",((ask(n,1)+1)%mod+mod)%mod);
    }
    View Code

    SPOJ34096 DIVCNTK

    这题也太鬼畜了,1可以数论分块,2可以moblus反演,3可以洲阁筛。

    #include<bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ll;
    const int N=1e5+7;
    bitset<N>vis;
    ll n,k,lim,w[N<<1],sp[N],g[N<<1],h[N<<1];
    int m,num,tot,pri[N],id1[N],id2[N];
    ll S(ll x,int y)
    {
        if(x<=1||pri[y]>x)return 0;
        int t=x<=lim?id1[x]:id2[n/x];
        ll ret=g[t]+h[t]-(k+1)*(y-1);
        for(int i=y;i<=tot&&1ll*pri[i]*pri[i]<=x;i++)
        {
            ll p=pri[i];
            for(int j=1;p*pri[i]<=x;p*=pri[i],j++)
            {
                t=x/p<=lim?id1[x/p]:id2[n/(x/p)];
                ret+=S(x/p,i+1)*(k*j+1)+k*(j+1)+1;
            }
        }
        return ret;
    }
    int main()
    {
        for(int i=2;i<N;i++)
        {
            if(!vis[i])pri[++tot]=i;
            for(int j=1;j<=tot&&i*pri[j]<N;j++)
            {
                vis[i*pri[j]]=1;
                if(i%pri[j]==0)break;
            }
        }
        num=tot;
        int T;scanf("%d",&T);
        while(T--)
        {
            scanf("%lld%lld",&n,&k),lim=sqrt(n);
            m=0;
            tot=upper_bound(pri+1,pri+num+1,lim)-pri-1;
            for(ll i=1,j;i<=n;i=j+1)
            {
                j=n/(n/i),w[++m]=n/i;
                if(w[m]<=lim)id1[w[m]]=m;else id2[n/w[m]]=m;
                g[m]=(w[m]-1)*k,h[m]=w[m]-1;
            }
            for(int j=1;j<=tot;j++)
            for(int i=1;1ll*pri[j]*pri[j]<=w[i];i++)
            {
                int t=w[i]/pri[j]<=lim?id1[w[i]/pri[j]]:id2[n/(w[i]/pri[j])];
                g[i]-=g[t]-(j-1)*k,h[i]-=h[t]-(j-1);
            }
            printf("%llu
    ",S(n,1)+1);
        }
    }
    View Code
  • 相关阅读:
    菜鸡的Java笔记
    Python 练习 进程
    laravel 目录结构
    mysql 操作详解
    菜鸡的Java笔记
    菜鸡的Java笔记
    菜鸡的Java笔记
    菜鸡的Java笔记 数字操作类
    【模板】多项式求逆
    交互题[CF1103B Game with modulo、CF1019B The hat、CF896B Ithea Plays With Chtholly]
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/11084254.html
Copyright © 2011-2022 走看看