日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

min_25筛详解

發布時間:2023/12/3 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 min_25筛详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

扯淡

min_25篩是由min_25提出的求積性函數前綴和的亞線性算法,和一個叫“擴展埃氏篩”的東西有著微妙的關系。

至于是什么關系,我也不太清楚,反正有人說很像有人說就是一個東西(霧)

這段話并不是廢話

約定

為了方便后面描述,這里寫一些用到的約定和符號表示,以免產生恐懼

111被開除正整數籍 也就是說“前綴和”之類的都是從222開始,對答案所求的前綴和同樣,最后手動加111

π(n)\pi(n)π(n)表示1~n1 \sim n1n中質數個數的規模(其實問題不大,后面就懂了)

pip_ipi?表示第iii個質數,單獨的ppp均表示質數

primeprimeprime表示質數集合 minp(i)minp(i)minp(i)表示iii的最小質因子

pcp^cpc表示一個只含一個質因子的數

流程

首先所求的函數f(n)f(n)f(n)需要滿足:

  • 是個積性函數
  • 在質數處的取值f(p)f(p)f(p)是一個關于ppp的多項式。我們把這個多項式拆成若干單項式分別計算在相加,這樣就變成了"f(p)f(p)f(p)的值是一個關于ppp的單項式",我們記為f(p)=pkf(p)=p^kf(p)=pk
  • f(pc)f(p^c)f(pc)的值可以快速計算
  • 首先考慮計算這個東西

    ∑i=2n[i∈prime]ik\sum_{i=2}^n[i\in prime]i^ki=2n?[iprime]ik

    注意是iki^kik不是f(i)f(i)f(i),雖然這里還沒有區別,但它們只是質數位置相等

    首先既然叫擴展埃氏篩先回憶一下埃氏篩在干什么:開始寫下所有正整數,然后從小到大,如果一個沒被篩說明它是質數,用它篩掉后面的倍數

    我們可以用這個思路計算上面的式子,先算出所有的和,再用質數篩掉所有合數項

    g(n,j)g(n,j)g(n,j)表示用前jjj個質數篩了之后剩余項的和

    g(n,j)=∑i=2n[i∈primeorminp(i)>pj]ikg(n,j)=\sum_{i=2}^n[i \in prime \quad or\quad minp(i)>p_j]i^kg(n,j)=i=2n?[iprimeorminp(i)>pj?]ik

    和就是g(n,π(n))g(n,\pi(\sqrt{n}))g(n,π(n?))

    注意合數的最小質因子不會超過n\sqrt nn?,所以如果pj2>np_j^2>npj2?>ng(n,j)=g(n,j?1)g(n,j)=g(n,j-1)g(n,j)=g(n,j?1)

    對剩下情況考慮轉移,即從g(n,j?1)g(n,j-1)g(n,j?1)去掉被pjp_jpj?刪掉的項

    g(n,j?1)=∑i=2n[i∈primeorminp(i)≥pj]g(n,j-1)=\sum_{i=2}^n[i\in prime \quad or \quad minp(i)\geq p_j]g(n,j?1)=i=2n?[iprimeorminp(i)pj?]

    如果腦子轉不過來,可以強行算

    [i∈primeorminp(i)≥pj][i\in prime \quad or \quad minp(i)\geq p_j][iprimeorminp(i)pj?]且不滿足[i∈primeorminp(i)>pj][i \in prime \quad or\quad minp(i)>p_j][iprimeorminp(i)>pj?]

    [i∈primeorminp(i)≥pj][i\in prime \quad or \quad minp(i)\geq p_j][iprimeorminp(i)pj?][i?prime]且[minp(i)≤pj][i \notin prime] 且 [minp(i)\leq p_j][i/?prime][minp(i)pj?]
    綜上
    [i?prime,minp(i)=pj][i \notin prime,minp(i)=p_j][i/?prime,minp(i)=pj?]

    所以

    g(n,j)=g(n,j?1)?∑i=2n[i?prime,minp(i)=pj]ikg(n,j)=g(n,j-1)-\sum_{i=2}^n[i \notin prime,minp(i)=p_j]i^kg(n,j)=g(n,j?1)?i=2n?[i/?prime,minp(i)=pj?]ik

    可以提一個pjp_jpj?出來,因為不能有質數,就把pjp_jpj?去掉,剛好是111

    g(n,j)=g(n,j?1)?pjk∑i=2?npj?[minp(i)≥pj]ikg(n,j)=g(n,j-1)-p_j^k\sum_{i=2}^{\lfloor\frac{n}{p_j}\rfloor}[minp(i)\geq p_j]i^kg(n,j)=g(n,j?1)?pjk?i=2?pj?n???[minp(i)pj?]ik

    再次觀察

    g(n,j)=∑i=2n[i∈primeorminp(i)>pj]ikg(n,j)=\sum_{i=2}^n[i \in prime \quad or\quad minp(i)>p_j]i^kg(n,j)=i=2n?[iprimeorminp(i)>pj?]ik

    發現可以拆成小于pjp_jpj?的質數和大于等于pjp_jpj?的所有數,第二個就是剛才的式子

    g(n,j)=g(n,j?1)?pjk(g(?npj?,j?1)?∑i=1j?1pik)g(n,j)=g(n,j-1)-p_j^k(g(\lfloor\frac{n}{p_j}\rfloor,j-1)-\sum_{i=1}^{j-1}p_i^k)g(n,j)=g(n,j?1)?pjk?(g(?pj?n??,j?1)?i=1j?1?pik?)

    注意nnn由于都是一直整除,所以只會有O(n)O(\sqrt n)O(n?)種取值,可以整除分塊找出來強行離散化。在記錄某個值vvv所在位置的時候,如果v>nv>\sqrt nv>n?,我們另開一個數組存到?nv?\lfloor\frac{n}{v}\rfloor?vn??里面

    然后后面只會用到最后一項,所以第二維可以滾掉

    求答案時,設

    S(n,j)=∑i=2n[minp(i)>pj]f(i)S(n,j)=\sum_{i=2}^n[minp(i)>p_j]f(i)S(n,j)=i=2n?[minp(i)>pj?]f(i)

    分質數和合數分別計算

    質數部分用ggg算出來的減去前jjj

    g(n,π(n))?∑i=1jpikg(n,\pi(\sqrt n))-\sum_{i=1}^jp^k_ig(n,π(n?))?i=1j?pik?

    合數部分枚舉最小質因子和它的次數

    ∑k=j+1pk≤n∑e=1pke≤nf(pke)(S(?npke?,k)+[e>1])\sum_{k=j+1}^{p_k\leq\sqrt n}\sum_{e=1}^{p_k^e\leq n}f(p_k^e)(S(\lfloor\frac{n}{p_k^e}\rfloor,k)+[e>1])k=j+1pk?n??e=1pke?n?f(pke?)(S(?pke?n??,k)+[e>1])

    [e>1][e>1][e>1]指如果指數大于111它本身就是合數,需要統計答案

    兩部分相加即可

    總復雜度大概O(n23)O(n^{2\over3})O(n32?)常數較小,大約2s2s2s1e101e101e10,3s3s3s1e111e111e11

    模板題

    #include <iostream> #include <cstdio> #include <cstring> #include <cctype> #include <cmath>#define MAXN 200005 using namespace std; typedef long long ll; const int MOD=1e9+7,INV6=(MOD+1)/6; inline int add(const int& x,const int& y){return x+y>=MOD? x+y-MOD:x+y;} inline int dec(const int& x,const int& y){return x<y? x-y+MOD:x-y;} int np[MAXN],pl[MAXN],cnt; inline void init(const int& N) {np[1]=1;for (int i=2;i<=N;i++){if (!np[i]) pl[++cnt]=i;int x;for (int j=1;(x=i*pl[j])<=N;j++){np[x]=1;if (i%pl[j]==0) break;}} } ll val[MAXN]; int tot; int g1[MAXN],g2[MAXN],sum1[MAXN],sum2[MAXN]; int key[MAXN],yek[MAXN]; ll n; int m; inline int getkey(const ll& v){return v<=m? key[v]:yek[n/v];} int S(ll n,int j) {if (pl[j]>=n) return 0;int k=getkey(n);int ans=dec(dec(g2[k],g1[k]),dec(sum2[j],sum1[j]));for (int k=j+1;k<=cnt&&(ll)pl[k]*pl[k]<=n;k++)for (ll e=1,pe=pl[k];pe<=n;e++,pe*=pl[k])ans=add(ans,pe%MOD*(pe%MOD-1)%MOD*(S(n/pe,k)+(e>1))%MOD); return ans; } int main() {scanf("%lld",&n);m=sqrt(n);init(m);for (ll l=1,r;l<=n;l=r+1){r=n/(n/l);val[++tot]=n/l;int t=val[tot]%MOD;g1[tot]=((ll)t*(t+1)/2)%MOD-1;g2[tot]=(ll)t*(t+1)%MOD*(2*t+1)%MOD*INV6%MOD-1;if (val[tot]<=m) key[val[tot]]=tot;else yek[n/(n/l)]=tot;}for (int j=1;j<=cnt;j++){for (int i=1;i<=tot&&(ll)pl[j]*pl[j]<=val[i];i++){int k=getkey(val[i]/pl[j]);g1[i]=dec(g1[i],(ll)pl[j]*dec(g1[k],sum1[j-1])%MOD);g2[i]=dec(g2[i],(ll)pl[j]*pl[j]%MOD*dec(g2[k],sum2[j-1])%MOD);} sum1[j]=add(sum1[j-1],pl[j]),sum2[j]=add(sum2[j-1],(ll)pl[j]*pl[j]%MOD);}printf("%d\n",S(n,0)+1);return 0; }

    總結

    以上是生活随笔為你收集整理的min_25筛详解的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。