SP34096 DIVCNTK - Counting Divisors (general) min_25篩
阿新 • • 發佈:2019-01-17
define 包含 dig 完全 main 而且 為我 數組 bps
我們設\(\begin{aligned}g(q,b)=\sum_{i = 1}^q [i是質數\or i的最小質因子>p_b]i^k\end{aligned}\)
\(\color{#0066ff}{ 題目描述 }\)
\(σ_0(i)\) 表示\(i\) 的約數個數
求\(S_k(n)=\sum_{i=1}^n\sigma_0(i^k)\mod 2^{64}\)
\(\color{#0066ff}{輸入格式}\)
第一行一個T為數據組數
接下來每組數據一個n,一個k
\(\color{#0066ff}{輸出格式}\)
每個詢問輸出一行
\(\color{#0066ff}{輸入樣例}\)
5
1 3
2 3
3 3
10 3
100 3
\(\color{#0066ff}{輸出樣例}\)
1
5
9
73
2302
\(\color{#0066ff}{數據範圍與提示}\)
\(T\leq 10^4,n,k\leq10^{10}\)
\(\color{#0066ff}{ 題解 }\)
設p為質數
則min_25篩的使用條件就是
1、\(f(p)\)為多項式。2、\(f(p^k)\)容易求出。3、\(f\)積性函數
因為\(f(p)\)是多項式而且是積性函數
我們考慮把\(f(p)\)拆項,這樣拆出來的就是完全積性函數
比如\(\varphi(p)=p-1,\varphi_1(p)=p,\varphi_2(p)=1\)
本題\(\sigma(p)=2\),一個常數qwq
設拆項後\(f(p)=p^k\)
我們設\(\begin{aligned}g(q,b)=\sum_{i = 1}^q [i是質數\or i的最小質因子>p_b]i^k\end{aligned}\)
簡單來說,\(g(q,b)\)就是經過b輪埃氏篩法剩下的所有\(\in [2,q]\)的數的k次冪的和
如何求g呢? 考慮遞推\(g(?,b-1)\to g(?,b)\)
\(g(q,b)=\left\{\begin{aligned}g(q,b-1)\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ q<p_b^2 \\ g(q,b-1)-p_b^k*(g(\lfloor \frac q {p_b} \rfloor , b-1)-g(p_{b-1},b-1)) \ \ \ \ \ \ q\ge p_b^2\end{aligned}\right.\)
若\(q<p_b^2\),所有q以內的合數都已經被篩掉,不會影響
否則,考慮本輪篩掉了哪些數
每個\(\leq \lfloor\frac q {p_b}\rfloor\)的且不含有\(\leq p_b\)的質因子的數的\(p_b\)倍都會在本輪篩掉
因為\(g(\lfloor \frac q {p_b} \rfloor , b-1)\)還包含了多余的質數,於是我們用其減去\(g(p_{b-1},b-1))\)就行了
不難發現,g數組可以滾動,而且根據遞推式,第二維完全可以不要
初始g(a,0)=a-1(不算1)
因為我們的操作都跟質數有關,打表可以發現,數列分塊的r有一些規律
當\(g[r_i]\ne g[r_{i-1}]\)時,說明\(r_i\)是質數
顯然這樣數組是開不下的,我們讓g用r的數組下標,這樣空間復雜度就是\(\sqrt n\)
設\(|p|\)素數集合大小,\(\begin{aligned}S(a,b)=\sum_{i=2}^a [i的最小質因子\ge p_b]f(i)\end{aligned}\)
設\(S(a,b)=\left\{\begin{aligned}0\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ a\leq p_b \\ g(a,|p|)-g(p_{b-1},|p|)+\sum_{i=b}^{|p|}\sum_{p_i^{t+1}\leq a}(S(\frac a {p_i^t} ,i+1)*f(p_i^t)+f(p_i^{t+ 1})) \ \ \ \ \ \ q\ge p_b^2\end{aligned}\right.\)
遞歸求解即可
#include<bits/stdc++.h>
#define LL long long
LL in() {
char ch; LL x = 0, f = 1;
while(!isdigit(ch = getchar()))(ch == '-') && (f = -f);
for(x = ch ^ 48; isdigit(ch = getchar()); x = (x << 1) + (x << 3) + (ch ^ 48));
return x * f;
}
const int maxn = 3e6 + 10;
LL n, k, sqt;
LL a[maxn], g[maxn];
int m, tot, pri[maxn];
int getid(LL x) { return x <= sqt? x : m - n / x + 1; }
unsigned LL getans(LL a, int b) {
if(a < pri[b]) return 0;
unsigned LL ans = (k + 1) * (g[getid(a)] - g[getid(pri[b - 1])]);
for(int i = b; i <= tot && (LL)pri[i] * pri[i] <= a; i++)
for(LL x = pri[i], f = k + 1; x * pri[i] <= a; x *= pri[i], f += k)
ans += (getans(a / x, i + 1) * f + f + k);
return ans;
}
int main() {
for(int T = in(); T --> 0;) {
n = in(), k = in();
sqt = sqrt(n);
tot = m = 0;
for(LL i = 1; i <= n; i = a[m] + 1)
a[++m] = n / (n / i), g[m] = a[m] - 1;
for(int i = 2; i <= sqt; i++)
if(g[i] != g[i - 1]) {
pri[++tot] = i;
LL s = (LL)i * i;
for(int j = m; a[j] >= s; j--)
g[j] -= g[getid(a[j] / i)] - g[i - 1];
}
printf("%llu\n", getans(n, 1) + 1);
}
return 0;
}
SP34096 DIVCNTK - Counting Divisors (general) min_25篩