传送门

题意:

统计\(k\)元组个数\((a_1,a_2,\cdots,a_n),1\leq a_i\leq n\)使得\(gcd(a_1,a_2,\cdots,a_k,n)=1\)。

定义\(f(n,k)\)为满足要求的\(k\)元组个数,现在要求出\(\sum_{i=1}^n f(i,k),1\leq n\leq 10^9,1\leq k\leq 1000\)。

思路:

首先来化简一下式子,题目要求的就是:

\[\begin{aligned}
&\sum_{i=1}^n\sum_{j=1}^n\cdots \sum_{k=1}^n gcd(i,j,\cdots, k,n)=1\\
=&\sum_{i=1}^n\sum_{j=1}^n\cdots \sum_{k=1}^n\sum_{d|i,j,\cdots,k,n}\mu(d)\\
=&\sum_{d|n}\mu(d)\sum_{i=1}^{\frac{n}{d}}\sum_{j=1}^{\frac{n}{d}}\cdots \sum_{k=1}^\frac{n}{d}1\\
=&\sum_{d|n}\mu(d) (\frac{n}{d})^k
\end{aligned}
\]

套路到此结束~然后观察到这个式子其实是一个狄利克雷卷积的形式,\(f(i)=\mu(i),g(i)=i^k\),上式则为:\(f*g_{(n)}\)。

那么题目要求的就是这个卷积的前缀和,注意两个积性函数的卷积也是积性函数,因为\(\mu*I=\varepsilon\),所以我们再构造一个积性函数\(h=I\),直接上杜教筛就行了。最后的式子是:

\[h(1)\cdot S(n) = \sum_{i=1}^ng(i)-\sum_{d=2}^n h(d)S(\lfloor\frac{n}{d}\rfloor)
\]

后半部分直接整除分块,至于\(\sum_{i=1}^ng(i)\),拉格朗日插值能在\(O(k)\)的时间复杂度解决。

代码如下(比赛的时候写得稍微有点乱):

  1. /*
  2. * Author: heyuhhh
  3. * Created Time: 2019/11/29 21:03:32
  4. */
  5. #include <iostream>
  6. #include <algorithm>
  7. #include <vector>
  8. #include <cmath>
  9. #include <set>
  10. #include <map>
  11. #include <iomanip>
  12. #define MP make_pair
  13. #define fi first
  14. #define se second
  15. #define sz(x) (int)(x).size()
  16. #define all(x) (x).begin(), (x).end()
  17. #define INF 0x3f3f3f3f
  18. #define Local
  19. #ifdef Local
  20. #define dbg(args...) do { cout << #args << " -> "; err(args); } while (0)
  21. void err() { std::cout << '\n'; }
  22. template<typename T, typename...Args>
  23. void err(T a, Args...args) { std::cout << a << ' '; err(args...); }
  24. #else
  25. #define dbg(...)
  26. #endif
  27. void pt() {std::cout << '\n'; }
  28. template<typename T, typename...Args>
  29. void pt(T a, Args...args) {std::cout << a << ' '; pt(args...); }
  30. using namespace std;
  31. typedef long long ll;
  32. typedef pair<int, int> pii;
  33. //head
  34. const int N = 1e4 + 5, MOD = 998244353;
  35. int n, k;
  36. ll qpow(ll a, ll b) {
  37. ll ans = 1;
  38. while(b) {
  39. if(b & 1) ans = ans * a % MOD;
  40. a = a * a % MOD;
  41. b >>= 1;
  42. }
  43. return ans;
  44. }
  45. struct Lagrange {
  46. static const int SIZE = 1005;
  47. ll f[SIZE], fac[SIZE], inv[SIZE], pre[SIZE], suf[SIZE];
  48. int n;
  49. inline void add(ll &x, int y) {
  50. x += y;
  51. if(x >= MOD) x -= MOD;
  52. }
  53. void init(int _n) {
  54. n = _n;
  55. fac[0] = 1;
  56. for (int i = 1; i < SIZE; ++i) fac[i] = fac[i - 1] * i % MOD;
  57. inv[SIZE - 1] = qpow(fac[SIZE - 1], MOD - 2);
  58. for (int i = SIZE - 1; i >= 1; --i) inv[i - 1] = inv[i] * i % MOD;
  59. //设置f初值,可以根据需要修改
  60. f[0] = 0;
  61. for (int i = 1; i <= n; ++i)
  62. f[i] = (f[i - 1] + qpow(i, k)) % MOD;
  63. }
  64. ll calc(ll x) {
  65. if (x <= n) return f[x];
  66. pre[0] = x % MOD;
  67. for (int i = 1; i <= n; ++i) pre[i] = pre[i - 1] * ((x - i) % MOD) % MOD;
  68. suf[n] = (x - n) % MOD;
  69. for (int i = n - 1; i >= 0; --i) suf[i] = suf[i + 1] * ((x - i) % MOD) % MOD;
  70. ll res = 0;
  71. for (int i = 0; i <= n; ++i) {
  72. ll tmp = f[i] * inv[n - i] % MOD * inv[i] % MOD;
  73. if (i) tmp = tmp * pre[i - 1] % MOD;
  74. if (i < n) tmp = tmp * suf[i + 1] % MOD;
  75. if ((n - i) & 1) tmp = MOD - tmp;
  76. add(res, tmp);
  77. }
  78. return res;
  79. }
  80. }lagrange;
  81. int mu[N], p[N];
  82. bool chk[N];
  83. int pre[N];
  84. void init() {
  85. mu[1] = 1;
  86. int cnt = 0;
  87. for(int i = 2; i <= N - 1; i++) {
  88. if(!chk[i]) p[++cnt] = i, mu[i] = -1;
  89. for(int j = 1; j <= cnt && i * p[j] <= N - 1; j++) {
  90. chk[i * p[j]] = 1;
  91. if(i % p[j] == 0) {mu[i * p[j]] = 0; break;}
  92. mu[i * p[j]] = -mu[i];
  93. }
  94. }
  95. for(int i = 1; i <= N - 1; i++) {
  96. int res = 0;
  97. for(int j = 1; 1ll * j * j <= i; j++) {
  98. if(i % j == 0) {
  99. int d1 = j, d2 = i / j;
  100. res = (res + 1ll * mu[d1] * qpow(d2, k) % MOD) % MOD;
  101. if(d1 != d2) res = (res + 1ll * mu[d2] * qpow(d1, k) % MOD) % MOD;
  102. if(res < 0) res += MOD;
  103. }
  104. }
  105. pre[i] = (pre[i - 1] + res) % MOD;
  106. }
  107. }
  108. map <int, ll> mp;
  109. ll djs(int n) {
  110. if(n < N) return pre[n];
  111. if(mp.find(n) != mp.end()) return mp[n];
  112. ll ans = lagrange.calc(n);
  113. for(int i = 2, j; i <= n; i = j + 1) {
  114. j = n / (n / i);
  115. ans -= 1ll * (j - i + 1) * djs(n / i) % MOD;
  116. if(ans < 0) ans += MOD;
  117. }
  118. return mp[n] = ans;
  119. }
  120. void run(){
  121. lagrange.init(k + 1);
  122. init();
  123. int ans = djs(n);
  124. cout << ans << '\n';
  125. }
  126. int main() {
  127. ios::sync_with_stdio(false);
  128. cin.tie(0); cout.tie(0);
  129. cout << fixed << setprecision(20);
  130. while(cin >> n >> k) run();
  131. return 0;
  132. }

EOJ Monthly 2019.11 E. 数学题(莫比乌斯反演+杜教筛+拉格朗日插值)的更多相关文章

  1. 洛谷P3768 简单的数学题 莫比乌斯反演+杜教筛

    题意简述 求出这个式子 \[ \sum_{i=1}^n\sum_{j=1}^n ij(i,j) \bmod p \] 做法 先用莫比乌斯反演拆一下式子 \[ \begin{split} \sum_{i ...

  2. 「洛谷P3768」简单的数学题 莫比乌斯反演+杜教筛

    题目链接 简单的数学题 题目描述 输入一个整数n和一个整数p,你需要求出 \[\sum_{i=1}^n\sum_{j=1}^n (i\cdot j\cdot gcd(i,j))\ mod\ p\]  ...

  3. LOJ#6229. 这是一道简单的数学题(莫比乌斯反演+杜教筛)

    题目链接 \(Description\) 求\[\sum_{i=1}^n\sum_{j=1}^i\frac{lcm(i,j)}{gcd(i,j)}\] 答案对\(10^9+7\)取模. \(n< ...

  4. luogu 3768 简单的数学题 (莫比乌斯反演+杜教筛)

    题目大意:略 洛谷传送门 杜教筛入门题? 以下都是常规套路的变形,不再过多解释 $\sum\limits_{i=1}^{N}\sum\limits_{j=1}^{N}ijgcd(i,j)$ $\sum ...

  5. [复习]莫比乌斯反演,杜教筛,min_25筛

    [复习]莫比乌斯反演,杜教筛,min_25筛 莫比乌斯反演 做题的时候的常用形式: \[\begin{aligned}g(n)&=\sum_{n|d}f(d)\\f(n)&=\sum_ ...

  6. 【bzoj3930】[CQOI2015]选数 莫比乌斯反演+杜教筛

    题目描述 我们知道,从区间[L,H](L和H为整数)中选取N个整数,总共有(H-L+1)^N种方案.小z很好奇这样选出的数的最大公约数的规律,他决定对每种方案选出的N个整数都求一次最大公约数,以便进一 ...

  7. [BZOJ 3930] [CQOI 2015]选数(莫比乌斯反演+杜教筛)

    [BZOJ 3930] [CQOI 2015]选数(莫比乌斯反演+杜教筛) 题面 我们知道,从区间\([L,R]\)(L和R为整数)中选取N个整数,总共有\((R-L+1)^N\)种方案.求最大公约数 ...

  8. 2019年南京网络赛E题K Sum(莫比乌斯反演+杜教筛+欧拉降幂)

    目录 题目链接 思路 代码 题目链接 传送门 思路 首先我们将原式化简: \[ \begin{aligned} &\sum\limits_{l_1=1}^{n}\sum\limits_{l_2 ...

  9. LOJ#6491. zrq 学反演(莫比乌斯反演 杜教筛)

    题意 题目链接 Sol 反演套路题? 不过最后一步还是挺妙的. 套路枚举\(d\),化简可以得到 \[\sum_{T = 1}^m (\frac{M}{T})^n \sum_{d \ | T} d \ ...

随机推荐

  1. Java读取本地json文件

    背景 之前一直在弄一个Java爬虫,将爬取的信息保存到了数据库中.但这毕竟是一个课程设计,在设计前端GUI,展示数据的时候最开始是直接通过select语句从数据库中查找的,但我担心交给老师后,老师还要 ...

  2. CF977D Divide by three, multiply by two

    题目链接 我同学在旁边做者道题,我也看了一下 真的好水难 一看这道题,直接搜索 剪枝是不可能剪枝的一辈子不可能 Code #include <cstdio> #include <io ...

  3. ribbon客户端负载均衡

    Ribbon简介 参考:https://blog.csdn.net/chengqiuming/article/details/80711168 Ribbon是Netflix发布的负载均衡器,它有助于控 ...

  4. C++调用bat并实现传值

    1.设置环境变量,这一类为路径 C++ void bat(const string& sDirC, const string& sDirD) { char Ddir[256]; Ddi ...

  5. Javascript获取元素的xpath

    //获取xpath function readXPath(element) { if (element.id !== "") {//判断id属性,如果这个元素有id,则显 示//* ...

  6. CSS入门(css简介与样式汇总、CSS的使用方式和特征、CSS基础选择器和复杂选择器、边框阴影)

    一.CSS的作用 1.以统一的方式实现样式的定义 2.提高页面样式的可重用性和可维护性 3.实现了内容(HTML)和表示(CSS)的分离 HTML和CSS之间有什么关系? HTML:构建网页的结构 C ...

  7. 关于for循环中使用setTimeout的四种解决方案

    我们先来简单了解一下setTimeout延时器的运行机制.setTimeout会先将回调函数放到等待队列中,等待区域内其他主程序执行完毕后,按时间顺序先进先出执行回调函数.本质上是作用域的问题. 因此 ...

  8. JavaWeb 错误/异常时页面提示

    经常我们会遇到发生页面404错误,服务器 500 异常,如果默认方式处理,则是将异常捕获之后跳到 Tomcat 缺省的异常页面,如下图所示.

  9. 二、VUE项目BaseCms系列文章:项目目录结构介绍

    一. 目录结构截图 二. 目录结构说明 - documents    存放项目相关的文档文件 - api   api 数据接口目录 - assets    资源文件目录 - components   ...

  10. ORA-14061: 不能更改索引分区列的数据类型或长度

    修改分区表主键时报错: 在行: 2 上开始执行命令时出错 -alter table KC23 modify AAZ210 VARCHAR2(50)错误报告 -SQL 错误: ORA-14061: 不能 ...