算法原理

本文参考了 zzq's blog 。

\(\text{powerful number}\) 的定义是每个质因子次数都 \(\ge 2\) 的数,有个结论是 \(\ge n\) 的 \(\text{powerful number}\) 只有 \(\mathcal O(\sqrt n)\) 个,如何找这些数呢?用暴力 \(\text{dfs}\) 从小到达枚举质因子及其幂次即可(类似于 \(\text{min_25}\) 第二部分)。

比如对于函数 \(F(p^q) = p^k\) 其中 \(p\) 为素数且 \(k\) 为定值,且 \(f(x)\) 是积性函数。我们需要求 \(\sum_{i = 1}^{n} F(i)\)。

考虑令 \(G(x) = x^k\) ,令 \(\displaystyle H = \frac F G\) (其中除法为狄利克雷卷积的逆运算),由于 \(F, G\) 都为积性函数,所以 \(H\) 也为积性函数。

我们考虑求出 \(H\) ,有 \(F(p) = G(p)H(1) + H(p)G(1)\) 由于 \(F(p) = G(p)\) 且 \(H(1) = 1, G(1) = 1\) 易求(我们通常令 \(F(1) = 1\) ),那么有 \(H(p) = 0\) ,又由于 \(H\) 为积性函数,所以 \(H(x)\) 只有当 \(x\) 为 \(\text{powerful number}\) 时有值。

有什么用呢?我们考虑原来的式子 \(\displaystyle\sum_{i = 1}^{n} F(i) = \sum_{ij \le n} H(i) G(j) = \sum_{i = 1}^{n} H(i) \sum_{j = 1}^{\lfloor \frac n i\rfloor} G(j)\) 。

现在只剩下一个问题,如何求 \(H(x)\) ,由于是积性函数,我们只需要求出 \(H(p^q)\) ,可以归纳出 \(H(p^q) = p^{k} - p^{2k}\) (读者自证不难)。

但是对于通用的 \(H(x)\) 如何求呢?我们考虑对于 \(p\) 的指数 \(q\) 来说,等价于多项式求逆,可以 \(\mathcal O(q)\) 递推一项。

然后我们可以利用插值等求自然数幂和的方式在 \(\mathcal O(k\sqrt n)\) 的时间求出对应的前缀和,比 \(\text{min_25}\) 优秀许多。

算法特点

  1. 复杂度是 \(\mathcal O(\sqrt n) \times \mathcal O(\text{calcG})\) ,所以大部分时候有显著的时间优势,而且十分简短好记。
  2. 但是 \(G(x)\) 通常十分难以构造,注意是我们要令 \(G(p) = F(p)\) 且 \(G(x)\) 为积性函数,有十分大的局限性。

实现

#include <bits/stdc++.h>#define For(i, l, r) for(register int i = int(l), i##end = int(r); i <= i##end; ++ i)
#define Fordown(i, r, l) for(register int i = int(r), i##end = int(l); i >= i##end; -- i)
#define Rep(i, r) for(register int i = int(0), i##end = int(r); i < i##end; ++ i)
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define Set(a, b) memset(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << x << endlusing namespace std;typedef long long ll;template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, T b) { return b > a ? a = b, 1 : 0; }template<typename T = int>
inline T read() {T x(0), sgn(1); char ch(getchar());for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1;for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48);return x * sgn;
}void File() {freopen ("function.in", "r", stdin);freopen ("function.out", "w", stdout);
}const int N = 1e7 + 1e3, Mod = 1e9 + 7, K = 25;ll n; int k;inline int fpm(int x, int power) {int res(1);for (; power; power >>= 1, x = 1ll * x * x % Mod)if (power & 1) res = 1ll * res * x % Mod;return res;
}bool is_prime[N]; int prime[N], prep[N], powp[N], pcnt;void Linear_Sieve(int maxn) {Set(is_prime, true); is_prime[0] = is_prime[1] = false;For (i, 2, maxn) {if (is_prime[i]) {prime[++ pcnt] = i;prep[pcnt] = (prep[pcnt - 1] + (powp[pcnt] = fpm(i, k))) % Mod;}for (int j = 1, res; j <= pcnt && (res = prime[j] * i) <= maxn; ++ j) {is_prime[res] = false; if (!(i % prime[j])) break;}}
}int pre[K], suf[K], fac[K], ifac[K], y[K];void Fac_Init(int maxn) {fac[0] = ifac[0] = 1;For (i, 1, maxn) y[i] = (y[i - 1] + fpm(i, k)) % Mod;For (i, 1, maxn) fac[i] = 1ll * fac[i - 1] * i % Mod;ifac[maxn] = fpm(fac[maxn], Mod - 2);Fordown (i, maxn - 1, 1) ifac[i] = ifac[i + 1] * (i + 1ll) % Mod;
}inline int Sumk(int m) {int maxn = k + 2, ans = 0;pre[0] = suf[maxn + 1] = 1;For (i, 1, maxn) pre[i] = 1ll * pre[i - 1] * (m - i) % Mod;Fordown (i, maxn, 1) suf[i] = 1ll * suf[i + 1] * (m - i) % Mod;For (i, 1, maxn) {int coef = 1ll * pre[i - 1] * suf[i + 1] % Mod, inv = ((maxn - i) & 1 ? -1ll : 1ll) * ifac[i - 1] * ifac[maxn - i] % Mod;ans = (ans + 1ll * coef * y[i] % Mod * inv) % Mod;}return ans;
}ll val[N]; int sum[N];int cnt, id1[N], id2[N], d, res[N];inline int &id(ll x) {return x <= d ? id1[x] : id2[n / x];
}int dcnt = 0;void Dfs(ll x, int cur, int coef) {(sum[id(n / x)] += coef) %= Mod;for (int i = cur + 1; i <= pcnt && x <= n / prime[i] / prime[i]; ++ i) {ll y = prime[i];do {y *= prime[i];Dfs(x * y, i, (powp[i] - 1ll * powp[i] * powp[i]) % Mod * coef % Mod);} while (y <= n / x / prime[i]);}
}int main() {File();n = read<ll>(); k = read();Fac_Init(k + 2); Linear_Sieve(d = sqrt(n + .5));for (ll i = 1; i <= n; i = n / (n / i) + 1) val[id(n / i) = ++ cnt] = n / i;Dfs(1, 0, 1);int ans = 0;For (i, 1, cnt) if (sum[i])ans = (ans + 1ll * sum[i] * Sumk(val[i] % Mod)) % Mod;printf ("%d\n", (ans + Mod) % Mod);return 0;}

转载于:https://www.cnblogs.com/zjp-shadow/p/11093242.html

powerful number求积性函数前缀和相关推荐

  1. 利用powerful number求积性函数前缀和

    好久没更博客了,先水一篇再说.其实这个做法应该算是杜教筛的一个拓展. powerful number的定义是每个质因子次数都 $\geq 2$ 的数.首先,$\leq n$ 的powerful num ...

  2. 2018ACM-ICPC南京赛区网络赛: J. Sum(积性函数前缀和)

    J. Sum A square-free integer is an integer which is indivisible by any square number except 11. For ...

  3. 51nod 1244 莫比乌斯函数之和(积性函数前缀和)

    关于积性函数前缀和的问题,可以关注糖老师的博客 关于积性函数前缀和的问题,可以关注糖老师的博客 http://blog.csdn.net/skywalkert/article/details/5050 ...

  4. 线性筛求积性函数的模板

    ACM常用模板合集 void sieve() {tot = 1;memset(vis, 0, sizeof(vis));low[1] = 1;G[1] = 函数G(n) n=1时的定义for (int ...

  5. 浅谈一类积性函数的前缀和(转载)

    本文转自:http://blog.csdn.net/skywalkert/article/details/50500009 另外,莫比乌斯反演和杜教筛其他可转到 http://blog.leanote ...

  6. 杜教筛【莫比乌斯前缀和,欧拉函数前缀和】推导与模板【一千五百字】

    下图给出杜教筛详细推导过程,前置知识有积性函数和莫比乌斯反演. 杜教筛是一种优秀的求积性函数前缀和算法,其时间复杂度受预处理数组的影响,一般开到2/3次幂大小,可使复杂度达到较为优秀的程度. 杜教筛的 ...

  7. 利用 Powerful Number 求数论函数前缀和

    利用 Powerful Number 求数论函数前缀和 0. 前言 Powerful Number 可以用来快速求解数论函数的前缀和. 本文参考了: zzq's blog 攀岩高手 的博客 在此向以上 ...

  8. 杜教筛(上):整除分块,积性函数,欧拉与莫比乌斯

    整除分块: 当我们求∑i=1nf(⌊ni⌋)\sum_{i=1}^nf(\lfloor\frac{n}{i}\rfloor)∑i=1n​f(⌊in​⌋)的时候,如果1到n求一遍感觉太傻了,因为会有很多 ...

  9. 积性函数的性质及证明 + 线性筛

    引言 在数论问题中,积性函数有着广泛的应用. 如在莫比乌斯反演问题中,函数变换之后如何快速维护前缀和往往是最重要也是最难的一步.如果维护的函数具有积性,那就可以尝试利用线性筛在O(n)O(n)O(n) ...

  10. 【算法专题】积性函数

    [参考] ★浅谈一类积性函数的前缀和 by skywalkert 任之洲数论函数.pdf 论逗逼的自我修养之寒假颓废记 by jiry_2 杜教筛 [学习笔记][更新中] by Candy? [变化技 ...

最新文章

  1. 【JavaSE_06】Java中的数组(array)-思维导图
  2. mysql问题举例_MySql问题总结
  3. 跨服务器Session共享的四种方法
  4. 第四章:Spring AOP
  5. 多个服务器数据互通_5月23日部分服务器数据互通公告!
  6. MySQL 集群 3副本,Kubernetes经典实践——运行MySQL多副本集群
  7. tensorflow搭建神经网络
  8. mysql请假表_[源码和文档分享]基于JSP和MYSQL数据库实现的请假管理系统
  9. 解决计算机主机与打印机共享打印机,主机上的打印机已经设置了共享可是另外的电脑却不能用也搜索不到共享打印机...
  10. Windows 80端口被System进程占用的解决
  11. Cypress Locators
  12. 【6035】聊聊各种“上门”能不能做起来
  13. WixSharp打包软件安装包入门教程
  14. Cassandra Cql
  15. 手把手教你做树莓派魔镜-MagicMirror(一)-准备工作
  16. 自己封装的数据库DbUtils的万能模板
  17. ChatGPT 是传统搜索引擎的终结?——Web3 创新 | Is ChatGPT The End Of Traditional Search Engines—Web3 Innovation
  18. 安卓4.4pppoe拨号间隔及轮次修改
  19. 【测试】18.系统测试及类型
  20. [mybatis异常:Could not find result map ......]

热门文章

  1. MyBatis中拦截器(Interceptor)实现原理分析
  2. 并发编程学习之JDK1.8的ConcurrentHashMap
  3. 并发学习之CyclicBarrier循环栅栏
  4. Dom4j 读取一个XML文件和将String写成XML文件
  5. Video Target Tracking Based on Online Learning—TLD多目标跟踪算法
  6. 类别的作用?继承和类别在实现中有何区别
  7. MOSS2007匿名调查列表使用分页符导致的错误分析
  8. android NDK如何解决Please define the NDK_PROJECT_PATH variable to point to it
  9. android进阶(三)数据存储之Internal Storage
  10. CF1399E2 Weights Division (hard version)