经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » C++ » 查看文章
LOJ#6491. zrq 学反演(莫比乌斯反演 杜教筛)
来源:cnblogs  作者:自为风月马前卒  时间:2018/12/13 10:24:03  对本文有异议

题意

题目链接

Sol

反演套路题? 不过最后一步还是挺妙的。

套路枚举\(d\),化简可以得到

\[\sum_{T = 1}^m (\frac{M}{T})^n \sum_{d \ | T} d \mu(\frac{T}{d})\]

后面的显然是狄利克雷卷积的形式,但是这里\(n \leqslant 10^{11}\)显然不能直接线性筛了

\(F(n) = n, f(n) = \phi(n)\)

根据欧拉函数的性质,有\(F(n) = \sum_{d \ | n} f(d)\)

反演一下

\[f(n) = \sum_{d \ | n} \mu(d) F(\frac{n}{d})\]

\[\phi(n) = \sum_{d \ |n} d \mu(\frac{n}{d})\]

那么原式等于

\[\sum_{T = 1}^m (\frac{M}{T})^n \phi(T)\]

然后杜教筛+数论分块一波

注意线性筛的范围最好设大一点

  1. #include<bits/stdc++.h>
  2. #define ull unsigned long long
  3. #define LL long long
  4. using namespace std;
  5. const int MAXN = 1e7 + 10;
  6. LL N, M, Lim;
  7. int vis[MAXN], prime[MAXN], tot;
  8. ull mp[MAXN], phi[MAXN];
  9. void get(int N) {
  10. vis[1] = phi[1] = 1;
  11. for(int i = 2; i <= N; i++) {
  12. if(!vis[i]) prime[++tot] = i, phi[i] = i - 1;
  13. for(int j = 1; j <= tot && i * prime[j] <= N; j++) {
  14. vis[i * prime[j]] = 1;
  15. if(!(i % prime[j])) {phi[i * prime[j]] = phi[i] * prime[j]; break;}
  16. else phi[i * prime[j]] = phi[i] * phi[prime[j]];
  17. }
  18. }
  19. for(int i = 2; i <= N; i++) phi[i] += phi[i - 1];
  20. }
  21. ull mul(ull x, ull y) {
  22. return x * y;
  23. }
  24. ull fp(ull a, ull p) {
  25. ull base = 1;
  26. while(p) {
  27. if(p & 1) base = mul(base, a);
  28. a = mul(a, a); p >>= 1;
  29. }
  30. return base;
  31. }
  32. ull S(LL x) {
  33. if(x <= Lim) return phi[x];
  34. else if(mp[M / x]) return mp[M / x];
  35. ull rt;
  36. rt = (x & 1) ? (x + 1) / 2 * (x) : (x / 2) * (x + 1);
  37. //rt = (x + 1) * x / 2;
  38. for(LL d = 2, nxt; d <= x; d = nxt + 1) {
  39. nxt = x / (x / d);
  40. rt -= (nxt - d + 1) * S(x / d);
  41. }
  42. return mp[M / x] = rt;
  43. }
  44. signed main() {
  45. cin >> N >> M;
  46. get(Lim = ((int)1e7));
  47. //for(int i = 1; i <= M; i++) printf("%d ", phi[i]);
  48. ull ans = 0;
  49. for(LL i = 1, nxt; i <= M; i = nxt + 1) {
  50. nxt = M / (M / i);
  51. ans += fp(M / i, N) * (S(nxt) - S(i - 1));
  52. // cout << i << '\n';
  53. }
  54. cout << ans;
  55. return 0;
  56. }
 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号