SP34096 DIVCNTK - Counting Divisors (general) min_25筛

\(\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;
}

原文地址:https://www.cnblogs.com/olinr/p/10281511.html

时间: 2024-07-31 13:03:48

SP34096 DIVCNTK - Counting Divisors (general) min_25筛的相关文章

SP34096 【DIVCNTK - Counting Divisors (general)】

题目 求 \[\sum_{i=1}^n \sigma(i^k)\] 我们先来设一个函数\(f(i)=\sigma(i^k)\) 根据约数个数定理 \[f(p)=\sigma(p^k)=k+1\] \[f(p^c)=\sigma(p^{ck})=ck+1\] 这不就可以Min_25筛了吗 还是先求出来一个区间内的质数个数,一个质数的贡献显然是\(k+1\),之后上板子就好了 代码 #include<algorithm> #include<iostream> #include<c

Counting Divisors HDU - 6069

Counting Divisors HDU - 6069 题意:给定区间[a,b]和k,求xk有多少因子(x属于[a,b]),求和. 题解:http://blog.csdn.net/zlh_hhhh/article/details/76680641 a.b最大可达到1e12,但是b-a<1e6. 一开始愚蠢的一个一个分解然后去求有多少因子然后求和,范围那么大裸裸的超时啊! 可以枚举素数,对每一个素数,把区间内所有可以分解的进行分解. 最后再求和. 1 #include <bits/stdc++

HDU 6069 Counting Divisors —— 2017 Multi-University Training 4

Counting Divisors Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 2599    Accepted Submission(s): 959 Problem Description In mathematics, the function d(n) denotes the number of divisors of p

hdu 6069 Counting Divisors(求因子的个数)

Counting Divisors Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)Total Submission(s): 3170    Accepted Submission(s): 1184 Problem Description In mathematics, the function d(n) denotes the number of divisors of

P4213 【模板】杜教筛(Sum) min_25筛

\(\color{#0066ff}{ 题目描述 }\) 给定一个正整数\(N(N\le2^{31}-1)\) 求 \(ans_1=\sum_{i=1}^n\varphi(i)\) \(ans_2=\sum_{i=1}^n \mu(i)\) \(\color{#0066ff}{输入格式}\) 一共T+1行 第1行为数据组数T(T<=10) 第2~T+1行每行一个非负整数N,代表一组询问 \(\color{#0066ff}{输出格式}\) 一共T行,每行两个用空格分隔的数ans1,ans2 \(\c

51Nod1222 最小公倍数计数 数论 Min_25 筛

原文链接https://www.cnblogs.com/zhouzhendong/p/51Nod1222.html 题意 给定 $a,b$, 求 $$\sum_{n=a}^b \sum_{i=1}^n \sum_{j=1}^i [{\rm lcm } (i,j) = n]$$ $$a,b\leq 10^{11}$$ $${\rm Time \ Limit } = 6s$$ 题解 本题做法很多. Min_25 筛 先差分一下,转化成求前缀和. 先把原题的统计无序数对转化成统计有序数对,最终 $an

UOJ188. 【UR #13】Sanrd [min_25筛]

传送门 思路 也可以算是一个板题了吧qwq 考虑min_25筛最后递归(也就是DP)的过程,要枚举当前最小的质因子是多少. 那么可以分类讨论,考虑现在这个质因子是否就是次大质因子. 如果不是,那么就是\(S(n/p,k+1)\):如果是,那么剩下的必定是一个更大的质数,那么就需要知道一段区间内有多少个质数. 质数个数显然可以min_25筛给搞出来. 于是就做完了. 代码 #include<bits/stdc++.h> clock_t t=clock(); namespace my_std{ u

LG5325 【模板】Min_25筛

P5325 [模板]Min_25筛 题目背景 模板题,无背景. 题目描述 定义积性函数$f(x)$,且$f(p^k)=p^k(p^k-1)$($p$是一个质数),求 $$\sum_{i=1}^n f(x)$$ 对$10^9+7$取模. 输入输出格式 输入格式: 一行一个整数$n$. 输出格式: 一个整数表示答案. 输入输出样例 输入样例#1: 复制 10 输出样例#1: 复制 263 输入样例#2: 复制 1000000000 输出样例#2: 复制 710164413 说明 $f(1)=1,f(

ZOJ The Sum of Unitary Totient (Min_25筛)

题意: 给你一个函数f(n)=(p1a1-1)(p2a2-1)...(prar-1) ,n=p1a1p2a2...prar  求\[\sum\limits_{i = 1}^n {f(i)} \],\[n <  = 1e9\] 思路: \[f(p) = p - 1,f({p^k}) = {p^k} - 1\],直接用min_25筛就可以了,按道理来讲我感觉min_25筛是稳过的,但我交了几十次才过,要不是在网上看到有人用min_25筛过了我还以为我想错了 #include<bits/stdc++