[关闭]
@nlogn 2019-07-11T10:20:38.000000Z 字数 3396 阅读 760

LuoguP3455 [POI2007]ZAP - Queries

题目描述

给定,求以下式子的值:

Input & Output's examples

Input's examples

  1. 2
  2. 4 5 2
  3. 6 4 3

Output's examples

  1. 3
  2. 2

分析

比较显然的Mobius反演题目,没学过莫反的别尝试暴力了

我们来一起推一下式子(注意:以下的分数默认向下取整)。

同时除一下:

由Mobius函数的定义式:

我们把代入可得。

所以,原式可以简化为:

我们变换枚举顺序,首先枚举,将它的求和符号提前,后面内容则变为布尔表达式

因为,那么我们只需要枚举的倍数即可,同时除一下:

显然恒成立,那么直接去掉。

已经消失,那么我们直接根据乘法分配率:

因为是不完全积性函数,我们可以求和。

但是本题要求多组数据,于是我们可以数论分块一下,然后预处理前缀和。

代码

  1. /* Headers */
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cmath>
  5. #include<cctype>
  6. #include<algorithm>
  7. #include<vector>
  8. #include<queue>
  9. #include<stack>
  10. #include<climits>
  11. #include<iostream>
  12. #include<map>
  13. #define FOR(i,a,b,c) for(int i=(a);i<=(b);i+=(c))
  14. #define ROF(i,a,b,c) for(int i=(a);i>=(b);i-=(c))
  15. #define FORL(i,a,b,c) for(long long i=(a);i<=(b);i+=(c))
  16. #define ROFL(i,a,b,c) for(long long i=(a);i>=(b);i-=(c))
  17. #define FORR(i,a,b,c) for(register int i=(a);i<=(b);i+=(c))
  18. #define ROFR(i,a,b,c) for(register int i=(a);i>=(b);i-=(c))
  19. #define lowbit(x) x&(-x)
  20. #define LeftChild(x) x<<1
  21. #define RightChild(x) (x<<1)+1
  22. #define RevEdge(x) x^1
  23. #define FILE_IN(x) freopen(x,"r",stdin);
  24. #define FILE_OUT(x) freopen(x,"w",stdout);
  25. #define CLOSE_IN() fclose(stdin);
  26. #define CLOSE_OUT() fclose(stdout);
  27. #define IOS(x) std::ios::sync_with_stdio(x)
  28. #define Dividing() printf("-----------------------------------\n");
  29. namespace FastIO{
  30. const int BUFSIZE = 1 << 20;
  31. char ibuf[BUFSIZE],*is = ibuf,*its = ibuf;
  32. char obuf[BUFSIZE],*os = obuf,*ot = obuf + BUFSIZE;
  33. inline char getch(){
  34. if(is == its)
  35. its = (is = ibuf)+fread(ibuf,1,BUFSIZE,stdin);
  36. return (is == its)?EOF:*is++;
  37. }
  38. inline int getint(){
  39. int res = 0,neg = 0,ch = getch();
  40. while(!(isdigit(ch) || ch == '-') && ch != EOF)
  41. ch = getch();
  42. if(ch == '-'){
  43. neg = 1;ch = getch();
  44. }
  45. while(isdigit(ch)){
  46. res = (res << 3) + (res << 1)+ (ch - '0');
  47. ch = getch();
  48. }
  49. return neg?-res:res;
  50. }
  51. inline void flush(){
  52. fwrite(obuf,1,os-obuf,stdout);
  53. os = obuf;
  54. }
  55. inline void putch(char ch){
  56. *os++ = ch;
  57. if(os == ot) flush();
  58. }
  59. inline void putint(int res){
  60. static char q[10];
  61. if(res==0) putch('0');
  62. else if(res < 0){putch('-');res = -res;}
  63. int top = 0;
  64. while(res){
  65. q[top++] = res % 10 + '0';
  66. res /= 10;
  67. }
  68. while(top--) putch(q[top]);
  69. }
  70. inline void space(bool x){
  71. if(!x) putch('\n');
  72. else putch(' ');
  73. }
  74. }
  75. inline void read(int &x){
  76. int rt = FastIO::getint();
  77. x = rt;
  78. }
  79. inline void print(int x,bool enter){
  80. FastIO::putint(x);
  81. FastIO::flush();
  82. FastIO::space(enter);
  83. }
  84. /* definitions */
  85. const int MAXN = 5e4 + 10;
  86. int n,m,d,u[MAXN];
  87. int T,prime[MAXN],cnt;
  88. bool isprime[MAXN];
  89. /* functions */
  90. inline long long solve(){
  91. long long ans = 0;
  92. scanf("%d%d%d",&n,&m,&d);
  93. if(n > m) std::swap(n,m);
  94. n /= d, m /= d;
  95. for(int i=1,j;i <= n;i = j + 1){
  96. j = std::min(n / (n / i), m / (m / i));
  97. ans += (long long) (u[j] - u[i - 1]) * (n / i) * (m / i);
  98. }
  99. return ans;
  100. }
  101. inline void init(){
  102. u[1] = 1;
  103. FOR(i,2,MAXN,1){
  104. if(!isprime[i]) u[i] = -1, prime[++cnt] = i;
  105. for(int j=1;j <= cnt && (long long) i * prime[j] <= MAXN;++j){
  106. isprime[i * prime[j]] = true;
  107. if(i % prime[j] == 0) break;
  108. u[i * prime[j]] = -u[i];
  109. }
  110. u[i] += u[i-1];
  111. }
  112. }
  113. int main(int argc,char *argv[]){
  114. init();
  115. scanf("%d",&T);
  116. while(T--) printf("%lld\n",solve());
  117. return 0;
  118. }

THE END

添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注