看見ntf和pb兩位大佬都來學了,然後就不自覺的來學了。
我們考慮這樣乙個問題。
$$ans=\sum_^nf(i)$$其中$1\leq n\leq 10^$
其中$f(i)$是乙個非常奇怪的函式,並不像$\mu(i),\varphi(i),i\varphi(i)$那樣具有那麼好的性質。但是滿足以下條件:
1.若$p$為質數,則$f(p)$是乙個關於$p$的多項式,比如$\mu(p)=-1,\varphi(p)=p-1$.
2.若$p$為質數,$e$為正整數,則$f(p^e)$可以很快求出。(通常是$o(1)$)
3.$f(n)$為積性函式。
然後就可以使用min_25篩了。(顧名思義是min_25發明的)
首先,我們需要知道min_25篩是埃氏篩的乙個拓展,它的思想很大一部分借助於埃氏篩。
回想一下埃氏篩,我們是每次將最小質因子為$p_i$的合數篩去,剩下的就是質數。
我們知道這些最小質因子至多為$\sqrt$,所以合數可以通過列舉最小質因子來計算,質數我們則使用另外的方法。
首先我們看質數的怎麼做。
$$\sum_^n[i\in prime]f(i)$$
根據條件1,我們知道$f(i)$是乙個多項式,這樣的話我們可以按照次數將$f(i)$拆成$i^k$之和,因為$i^k$是乙個完全積性函式(很快就有用的)。
$$\sum_^n[i\in prime]i^k$$
為了計算這個,我們需要引入乙個輔助陣列$g(n,j)$。(鬼知道是怎麼想到的)
$$g(n,j)=\sum_^n[i\in prime \ or \ minp(i)>p_j]i^k$$
其中$minp(i)$表示$i$的最小質因子,所以
$$\sum_^n[i\in prime]i^k=g(n,|p|)$$
既然我們要使用質數,所以我們可以先用尤拉篩把所有$\leq \sqrt$的質數篩出來,同時還要預處理$\sum_^j[i\in prime]i^k$.
我們考慮dp計算。既然是埃氏篩,我們就要在$g(n,j-1)$中最小質因子為$p_j$的合數篩去。]'
對於$p_j\geq \sqrt$的就不用管它了,因為肯定不可能。
首先,由於它是完全積性函式,所以$p_j$可以直接提出來,剩下的減去$i\leq \lfloor\frac\rfloor$中的數就可以了。
這些數中要求質因子$\geq p_j$,所以是$g(\lfloor\frac\rfloor,j-1)$,但是這裡面質數被重複計算了,所以要減去裡面的質數。
$$g(n,j)=g(n,j-1)-p_j^k(g(\lfloor\frac\rfloor,j-1)-\sum_^[i\in prime]i^k)$$
但是這樣的話是$o(n*|p|)$的,時間和空間都承受不了。但是我們發現我們可以使用乙個優化。
我們發現$g(n,j)$中$n$只有$o(\sqrt)$種取值,因為每次遞迴的時候是$n$變為$\lfloor\frac\rfloor$,而我們發現
$$\lfloor\frac\rfloor}\rfloor=\lfloor\frac\rfloor$$
所以$n$只會變為$\lfloor\frac\rfloor$,於是我們就直接「手動」離散化,這個可以看**。
然後$g(n,j)$的第二維也可以滾動陣列滾掉。所以時間$o(\sqrt*|p|)$,空間$o(\sqrt)$.
預處理部分終於結束了,接下來我們考慮計算答案,首先我們還是需要乙個輔助陣列。
$$s(n,j)=\sum_^n[minp(i)>p_j]f(i)$$
像上面說的一樣,分質數和合數兩類計算。
$$s(x,y)=g(x,|p|)-\sum_^f(p_i)+\sum_,k>j}\sum_f(p_k^e)(s(\lfloor\frac\rfloor,k)+[e>1])$$
前面兩項指的是質數,後面的和式是列舉最小質因子$p_k$和它的次數$e$,
這個跟$g$不同,$s$是要按照第二維倒著計算的,但是我們也可以使用遞迴的方法來計算。
$s(n,0)+f(1)$就是最終答案。
至於上面說的那個手動離散化,我們要開兩個陣列$id1$和$id2$,分別記錄$\leq \sqrt$和$>\sqrt$的部分的數值的編號。這樣就不用map了,可以省掉乙個log。
至於時間複雜度?我也不知道,總之跟杜教篩差不多,甚至有時候比杜教篩還要快。
1 #include2luogu5325#define rint register ll
3using
namespace
std;
4 typedef long
long
ll;5
const
int n = 1000003, mod = 1e9 + 7, inv2 = 500000004, inv3 = 333333336;6
ll n, sqr, pri[n], tot, pre1[n], pre2[n], ind1[n], ind2[n], g1[n], g2[n], w[n], cnt;
7bool
notp[n];
8 inline void
init(ll m)
16for(rint j = 1;j <= tot && i * pri[j] <= m;j ++)20}
21}22 inline ll s(ll x, int
y)32}33
return ans %mod;34}
35int
main()
48for(rint i = 1;i <= tot;i ++)
49for(rint j = 1;j <= cnt && pri[i] * pri[i] <= w[j];j ++)
56 printf("
%lld
", (s(n, 0) + 1) %mod);
57 }
練習題:
uoj188
Min 25 篩學習筆記
資料和 出處 資料2資料3 打死我也不承認參考了yyb的 min 25 篩可以幹嘛?下文中未特殊說明 p 均指質數集合,p i 或 p 指某個具體質數。求一類積性函式 f x 的字首和,需要滿足 f p 可以寫成多項式的形式,或者操作一下可以寫成多項式 如例題 且 f p k 能快速求出。講真學這個...
Min 25 篩 學習筆記
埃氏篩法 整除分塊 這裡有提到 1.問題模型 2.min 25 篩 3.模板題以及模板 有乙個積性函式 f 對於所有質數 p f p 是關於 p 的多項式,f p k 非常容易計算 不一定是關於 p 的多項式 求 sum f i n leq 10 1s 設集合 p 表示素數集合。設 g sum f ...
Min 25篩 學習筆記
這兒只是乙個簡單說明 概括 總結。原理見這 min 25篩用來求積性函式字首和。範圍一般是 10 要求所求積性函式在 f i 已知時,f p times i p in primes,i times p in 1,n 能快速計算。首先計算 g n,j sum if i quad i是質數 或 i的最小...