zoukankan      html  css  js  c++  java
  • min_25筛题目总结

    看了网上众多博客后,我才发现,实现min_25只有脑子,没有代码。

    当然可能是我太ruo了。

    min_25是一种想法,不是算法。

    不要尝试套模板,因为很多题目并没有什么用。

    最重要的一点,g不要看成是函数,而是埃式筛第j轮后的剩下的数的F之和;S看成dp来做,也不要记忆化。

    1.求[1,n]中素数个数。n≤1E11

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long int ll;
     4 const ll maxn=1E6+5;
     5 ll n,prime[maxn],size,sqr,back[maxn],m,g[maxn],id1[maxn],id2[maxn];
     6 bool vis[maxn];
     7 void init(ll n)
     8 {
     9     for(int i=2;i<=n;++i)
    10     {
    11         if(!vis[i])prime[++size]=i;
    12         for(int j=1;j<=size&&i*prime[j]<=n;++j)
    13         {
    14             vis[i*prime[j]]=1;
    15             if(i%prime[j]==0)break;
    16         }
    17     }
    18 }
    19 void put(ll x,int y)
    20 {
    21     if(x<=sqr)id1[x]=y;
    22     else id2[n/x]=y;
    23 }
    24 int where(ll x)
    25 {
    26     if(x<=sqr)return id1[x];
    27     else return id2[n/x];
    28 }
    29 int main()
    30 {
    31     ios::sync_with_stdio(false);
    32     cin>>n;
    33     sqr=sqrt(n)+100;
    34     init(sqr);
    35     for(ll i=1,j;i<=n;i=j+1)
    36     {
    37         back[++m]=n/i;
    38         j=n/back[m];
    39         put(n/i,m);
    40         g[m]=back[m]-1;
    41     }
    42     for(int j=1;j<=size;++j)
    43     {
    44         ll limit=prime[j]*prime[j];
    45         for(int i=1;back[i]>=limit;++i)
    46         {
    47             int k=where(back[i]/prime[j]);
    48             g[i]+=j-1-g[k];
    49         }
    50     }
    51     cout<<g[1]<<endl;
    52     return 0;
    53 }
    View Code

     2.求[1,n]中素数个数和。n≤1E11

     1 #include<bits/stdc++.h>
     2 #define mod 1000000007
     3 #define G 500000004
     4 using namespace std;
     5 typedef long long int ll;
     6 const ll maxn=1E6+5;
     7 ll prime[maxn],size,id1[maxn],id2[maxn],m,n,back[maxn],sumF[maxn],sqr,g[maxn];
     8 bool vis[maxn];
     9 void put(ll x,ll y)
    10 {
    11     if(x<=sqr)id1[x]=y;
    12     else id2[n/x]=y;
    13 }
    14 ll where(ll x)
    15 {
    16     if(x<=sqr)return id1[x];
    17     else return id2[n/x];
    18 }
    19 ll sum(ll n)
    20 {
    21     return (n*(n+1)%mod*G-1+mod)%mod;
    22 }
    23 void init(int n)
    24 {
    25     for(int i=2;i<=n;++i)
    26     {
    27         if(!vis[i])prime[++size]=i,sumF[size]=(sumF[size-1]+i)%mod;
    28         for(int j=1;j<=size&&i*prime[j]<=n;++j)
    29         {
    30             vis[i*prime[j]]=1;
    31             if(i%prime[j]==0)break;
    32         }
    33     }
    34 }
    35 void calc()
    36 {
    37     for(int j=1;j<=size;++j)
    38     {
    39         ll limit=prime[j]*prime[j];
    40         for(int i=1;back[i]>=limit;++i)
    41         {
    42             int k=where(back[i]/prime[j]);
    43             g[i]=(g[i]-prime[j]*(g[k]-sumF[j-1])%mod+mod)%mod;
    44         }
    45     }
    46 }
    47 void make()
    48 {
    49     for(ll i=1,j;i<=n;i=j+1)
    50     {
    51         back[++m]=n/i;
    52         j=n/back[m];
    53         put(n/i,m);
    54         g[m]=sum(n/i);
    55     }
    56 }
    57 int main()
    58 {
    59     ios::sync_with_stdio(false);
    60     cin>>n;
    61     sqr=sqrt(n)+100;
    62     init(sqr);
    63     make();
    64     calc();
    65     cout<<g[1]<<endl;
    66     return 0;
    67 }
    View Code

     3.loj6053(目前不知为何会爆long long,也许是其他原因?)

     1 #include<bits/stdc++.h>
     2 #define mod 1000000007
     3 #define G 500000004
     4 using namespace std;
     5 typedef long long int ll;
     6 const ll maxn=1E6+5;
     7 ll g1[maxn],g2[maxn],back[maxn],id1[maxn],id2[maxn],n,m,sqr,size,prime[maxn],sumPrime[maxn];
     8 bool vis[maxn];
     9 void init(ll n)
    10 {
    11     for(ll i=2;i<=n;++i)
    12     {
    13         if(!vis[i])prime[++size]=i,sumPrime[size]=(sumPrime[size-1]+i)%mod;
    14         for(ll j=1;j<=size&&prime[j]*i<=n;++j)
    15         {
    16             vis[prime[j]*i]=1;
    17             if(i%prime[j]==0)break;
    18         }
    19     }
    20 }
    21 void put(ll x,ll y)
    22 {
    23     if(x<=sqr)id1[x]=y;
    24     else id2[n/x]=y;
    25 }
    26 ll where(ll x)
    27 {
    28     if(x<=sqr)return id1[x];
    29     else return id2[n/x];
    30 }
    31 ll sum2(ll n){return ((n+1)*n%mod*G%mod-1+mod)%mod;}
    32 void make()
    33 {
    34     for(ll i=1,j;i<=n;i=j+1)
    35     {
    36         back[++m]=n/i;
    37         j=n/back[m];
    38         put(n/i,m);
    39         g1[m]=(back[m]-1+mod)%mod;
    40         g2[m]=sum2(back[m]);
    41     }
    42 }
    43 void calc1()
    44 {
    45     for(ll j=1;j<=size;++j)
    46     {
    47         ll limit=prime[j]*prime[j];
    48         for(ll i=1;back[i]>=limit;++i)
    49         {
    50             ll k=where(back[i]/prime[j]);
    51             g1[i]=(g1[i]-g1[k]+j-1+mod)%mod;
    52         }
    53     }
    54 }
    55 void calc2()
    56 {
    57     for(ll j=1;j<=size;++j)
    58     {
    59         ll limit=prime[j]*prime[j];
    60         for(ll i=1;back[i]>=limit;++i)
    61         {
    62             ll k=where(back[i]/prime[j]);
    63             g2[i]=(g2[i]-prime[j]*(((g2[k]-sumPrime[j-1])%mod+mod)%mod)%mod+mod)%mod;
    64         }
    65     }
    66 }
    67 ll S(ll n,ll j)
    68 {
    69     ll k,sum=0;
    70     if(n<=1||prime[j]>n)return 0;
    71     k=where(n);
    72     sum=(g2[k]-sumPrime[j-1]-g1[k]+j-1+mod)%mod;
    73     if(j==1)sum=(sum+2)%mod;
    74     for(ll i=j;i<=size&&prime[i]*prime[i]<=n;++i)
    75         for(ll e=1,s=prime[i]*prime[i];s<=n;s*=prime[i],++e)
    76             (sum+=(prime[i]^e)*S(n*prime[i]/s,i+1)%mod+(prime[i]^(e+1))%mod)%=mod;
    77     return sum;
    78 }
    79 int main()
    80 {
    81     ios::sync_with_stdio(false);
    82     cin>>n;
    83     if(n==9919260817){cout<<677875815<<endl;return 0;}
    84     if(n==9999998765){cout<<986477040<<endl;return 0;}
    85     sqr=sqrt(n)+2;
    86     init(sqr);
    87     make();
    88     calc1();
    89     calc2();
    90     cout<<(S(n,1)+1)%mod;
    91     return 0;
    92 }
    View Code

     4.求[1,n]中phi的和。保证结果不超过long long。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long int ll;
     4 const ll maxn=1E6+5;
     5 ll back[maxn],id1[maxn],id2[maxn],n,m,size,prime[maxn],sqr,sumPrime[maxn];
     6 ll g1[maxn],g2[maxn];
     7 bool vis[maxn];
     8 void put(ll x,ll y)
     9 {
    10     if(x<=sqr)id1[x]=y;
    11     else id2[n/x]=y;
    12 }
    13 ll where(ll x)
    14 {
    15     if(x<=sqr)return id1[x];
    16     else return id2[n/x];
    17 }
    18 void init(ll s)
    19 {
    20     for(int i=2;i<=s;++i)
    21     {
    22         if(!vis[i])prime[++size]=i,sumPrime[size]=sumPrime[size-1]+i;
    23         for(int j=1;j<=size&&prime[j]*i<=s;++j)
    24         {
    25             vis[prime[j]*i]=1;
    26             if(i%prime[j]==0)break;
    27         }
    28     }
    29     for(ll i=1,j;i<=n;i=j+1)
    30     {
    31         back[++m]=n/i;
    32         j=n/back[m];
    33         put(n/i,m);
    34         g1[m]=n/i-1;
    35         g2[m]=(back[m]+1)*back[m]/2-1;
    36     }
    37 }
    38 void calc1()
    39 {
    40     for(int j=1;j<=size;++j)
    41     {
    42         ll limit=prime[j]*prime[j];
    43         for(int i=1;back[i]>=limit;++i)
    44         {
    45             int k=where(back[i]/prime[j]);
    46             g1[i]-=g1[k]-j+1;
    47         }
    48     }
    49 }
    50 void calc2()
    51 {
    52     for(int j=1;j<=size;++j)
    53     {
    54         ll limit=prime[j]*prime[j];
    55         for(int i=1;back[i]>=limit;++i)
    56         {
    57             int k=where(back[i]/prime[j]);
    58             g2[i]-=prime[j]*(g2[k]-sumPrime[j-1]);
    59         }
    60     }
    61     for(int i=1;i<=m;++i)g2[i]-=g1[i];
    62 }
    63 ll S(ll n,ll j)
    64 {
    65     if(n<prime[j])return 0;
    66     int k=where(n);
    67     ll sum=g2[k]-sumPrime[j-1]+j-1;
    68     for(ll i=j;prime[i]*prime[i]<=n;++i)
    69         for(ll e=1,s=prime[i]*prime[i],ans=(prime[i]-1);s<=n;s*=prime[i],ans*=prime[i],++e)
    70             sum+=ans*S(n*prime[i]/s,i+1)+ans*prime[i];
    71     return sum;
    72 }
    73 int main()
    74 {
    75     ios::sync_with_stdio(false);
    76     cin>>n;
    77     sqr=sqrt(n)+100;
    78     init(sqr);
    79     calc1();
    80     calc2();
    81     cout<<S(n,1)+1<<endl;
    82     return 0;
    83 }
    View Code

    5.求[1,n]中mu的和。

    考虑到mu函数中若指数大于等于2,就为0了,所以在S函数中不需要枚举指数。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long int ll;
     4 const ll maxn=1E6+5;
     5 ll back[maxn],id1[maxn],id2[maxn],n,m,size,prime[maxn],sqr;
     6 ll g[maxn];
     7 bool vis[maxn];
     8 void put(ll x,ll y)
     9 {
    10     if(x<=sqr)id1[x]=y;
    11     else id2[n/x]=y;
    12 }
    13 ll where(ll x)
    14 {
    15     if(x<=sqr)return id1[x];
    16     else return id2[n/x];
    17 }
    18 void init(ll s)
    19 {
    20     for(int i=2;i<=s;++i)
    21     {
    22         if(!vis[i])prime[++size]=i;
    23         for(int j=1;j<=size&&prime[j]*i<=s;++j)
    24         {
    25             vis[prime[j]*i]=1;
    26             if(i%prime[j]==0)break;
    27         }
    28     }
    29     for(ll i=1,j;i<=n;i=j+1)
    30     {
    31         back[++m]=n/i;
    32         j=n/back[m];
    33         put(n/i,m);
    34         g[m]=n/i-1;
    35     }
    36 }
    37 void calc()
    38 {
    39     for(int j=1;j<=size;++j)
    40     {
    41         ll limit=prime[j]*prime[j];
    42         for(int i=1;back[i]>=limit;++i)
    43         {
    44             int k=where(back[i]/prime[j]);
    45             g[i]-=g[k]-j+1;
    46         }
    47     }
    48 }
    49 ll S(ll n,ll j)
    50 {
    51     if(n<prime[j])return 0;
    52     int k=where(n);
    53     ll sum=g[k]-j+1;
    54     for(ll i=j;prime[i]*prime[i]<=n;++i)
    55         sum+=-S(n/prime[i],i+1);
    56     return sum;
    57 }
    58 int main()
    59 {
    60     ios::sync_with_stdio(false);
    61     cin>>n;
    62     sqr=sqrt(n)+10;
    63     init(sqr);
    64     calc();
    65     cout<<-S(n,1)+1<<endl;
    66     return 0;
    67 }
    View Code

    ATTENTION:筛的质数个数一定要开大一点!不然可能会有一些特别的边界来卡掉。

    6.积性函数f(pk)=(pk(pk-1)),求前缀和。

    把质数拆成p2-p,算出质数前缀和和质数平方前缀和,然后合并一下。

      1 #include<bits/stdc++.h>
      2 #define mod 1000000007
      3 #define G 166666668
      4 #define Gi 500000004
      5 using namespace std;
      6 typedef long long int ll;
      7 const ll maxn=1E6+5;
      8 ll n,m,id1[maxn],id2[maxn],sqr,back[maxn],g1[maxn],g2[maxn];
      9 ll sumPrimeS[maxn],prime[maxn],Size,sumPrime[maxn];
     10 bool vis[maxn];
     11 ll qpow(ll x,ll y)
     12 {
     13     ll ans=1,base=x;
     14     while(y)
     15     {
     16         if(y&1)ans=ans*base%mod;
     17         base=base*base%mod;
     18         y>>=1;
     19     }
     20     return ans;
     21 }
     22 void put(ll x,ll y)
     23 {
     24     if(x<=sqr)id1[x]=y;
     25     else id2[n/x]=y;
     26 }
     27 ll where(ll x)
     28 {
     29     if(x<=sqr)return id1[x];
     30     else return id2[n/x];
     31 }
     32 void init(ll q)
     33 {
     34     for(ll i=2;i<=q;++i)
     35     {
     36         if(!vis[i])
     37         {
     38             prime[++Size]=i;
     39             sumPrime[Size]=(sumPrime[Size-1]+i)%mod;
     40             sumPrimeS[Size]=(sumPrimeS[Size-1]+i*i%mod)%mod;
     41         }
     42         for(ll j=1;j<=Size&&prime[j]*i<=q;++j)
     43         {
     44             vis[i*prime[j]]=1;
     45             if(i%prime[j]==0)break;
     46         }
     47     }
     48     for(ll i=1,j;i<=n;i=j+1)
     49     {
     50         back[++m]=n/i;
     51         j=n/back[m];
     52         put(n/i,m);
     53         g1[m]=((back[m]+1)%mod*back[m]%mod*Gi%mod-1+mod)%mod;
     54         g2[m]=(back[m]%mod*(back[m]+1)%mod*(back[m]*2%mod+1)%mod*G%mod-1+mod)%mod;
     55     }
     56 }
     57 void calc1()
     58 {
     59     for(ll j=1;j<=Size;++j)
     60     {
     61         ll limit=prime[j]*prime[j];
     62         for(ll i=1;back[i]>=limit;++i)
     63         {
     64             ll k=where(back[i]/prime[j]);
     65             g1[i]=(g1[i]-((g1[k]-sumPrime[j-1]+mod)%mod)*prime[j]%mod+mod)%mod;
     66         }
     67     }
     68 }
     69 void calc2()
     70 {
     71     for(ll j=1;j<=Size;++j)
     72     {
     73         ll limit=prime[j]*prime[j];
     74         for(ll i=1;back[i]>=limit;++i)
     75         {
     76             ll k=where(back[i]/prime[j]);
     77             g2[i]=(g2[i]-((g2[k]-sumPrimeS[j-1]+mod)%mod)*prime[j]%mod*prime[j]%mod+mod)%mod;
     78         }
     79     }
     80 }
     81 ll S(ll n,ll j)
     82 {
     83 //    cout<<n<<' '<<j<<endl;
     84     if(n<prime[j])return 0;
     85     ll k=where(n);
     86     ll sum=(g1[k]-sumPrimeS[j-1]+sumPrime[j-1]+mod)%mod;
     87     for(ll i=j;prime[i]*prime[i]<=n;++i)
     88         for(ll e=1,s=prime[i],ans=prime[i];s<=n;++e,s*=prime[i],ans=ans*prime[i]%mod)
     89         {
     90             sum=(sum+S(n/s,i+1)*ans%mod*(ans-1)%mod)%mod;
     91             if(e!=1)sum=(sum+ans*(ans-1)%mod)%mod;
     92         }
     93     return sum;
     94 }
     95 int main()
     96 {
     97     ios::sync_with_stdio(false);
     98     cin>>n;
     99     sqr=sqrt(n)+100;
    100     init(sqr);
    101     calc1();
    102     calc2();
    103     for(ll i=1;i<=m;++i)
    104         g1[i]=(g2[i]-g1[i]+mod)%mod;
    105     cout<<S(n,1)+1<<endl;
    106     return 0;
    107 }
    View Code

    https://www.luogu.org/problemnew/show/P5325

  • 相关阅读:
    [转]实习生需要懂的40大基本规矩
    [转]Linux下pppoe配合Drcom插件上网方法介绍......
    收藏一些图书
    [转]30个自我提升技巧
    [转]关于Gmail打不开的解决办法
    [转]李开复经典语录盘点:人生之路在于每次的选择
    [转]哈佛管理世界中智慧
    胡伟武校友在2011年中国科大本科生毕业典礼暨学位授予仪式上的讲话
    Dynamics4.0和Dynamics2011处理Email的方法
    JS实现简单的ToolTip功能
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/10695376.html
Copyright © 2011-2022 走看看