@nlogn
2019-07-11T02:20:38.000000Z
字数 3396
阅读 950
给定,求以下式子的值:
24 5 26 4 3
32
比较显然的Mobius反演题目,没学过莫反的别尝试暴力了
我们来一起推一下式子(注意:以下的分数默认向下取整)。
同时除一下:
由Mobius函数的定义式:
我们把代入可得。
所以,原式可以简化为:
我们变换枚举顺序,首先枚举,将它的求和符号提前,后面内容则变为布尔表达式
因为,那么我们只需要枚举的倍数即可,同时除一下:
显然恒成立,那么直接去掉。
已经消失,那么我们直接根据乘法分配率:
因为是不完全积性函数,我们可以求和。
但是本题要求多组数据,于是我们可以数论分块一下,然后预处理前缀和。
/* Headers */#include<cstdio>#include<cstring>#include<cmath>#include<cctype>#include<algorithm>#include<vector>#include<queue>#include<stack>#include<climits>#include<iostream>#include<map>#define FOR(i,a,b,c) for(int i=(a);i<=(b);i+=(c))#define ROF(i,a,b,c) for(int i=(a);i>=(b);i-=(c))#define FORL(i,a,b,c) for(long long i=(a);i<=(b);i+=(c))#define ROFL(i,a,b,c) for(long long i=(a);i>=(b);i-=(c))#define FORR(i,a,b,c) for(register int i=(a);i<=(b);i+=(c))#define ROFR(i,a,b,c) for(register int i=(a);i>=(b);i-=(c))#define lowbit(x) x&(-x)#define LeftChild(x) x<<1#define RightChild(x) (x<<1)+1#define RevEdge(x) x^1#define FILE_IN(x) freopen(x,"r",stdin);#define FILE_OUT(x) freopen(x,"w",stdout);#define CLOSE_IN() fclose(stdin);#define CLOSE_OUT() fclose(stdout);#define IOS(x) std::ios::sync_with_stdio(x)#define Dividing() printf("-----------------------------------\n");namespace FastIO{const int BUFSIZE = 1 << 20;char ibuf[BUFSIZE],*is = ibuf,*its = ibuf;char obuf[BUFSIZE],*os = obuf,*ot = obuf + BUFSIZE;inline char getch(){if(is == its)its = (is = ibuf)+fread(ibuf,1,BUFSIZE,stdin);return (is == its)?EOF:*is++;}inline int getint(){int res = 0,neg = 0,ch = getch();while(!(isdigit(ch) || ch == '-') && ch != EOF)ch = getch();if(ch == '-'){neg = 1;ch = getch();}while(isdigit(ch)){res = (res << 3) + (res << 1)+ (ch - '0');ch = getch();}return neg?-res:res;}inline void flush(){fwrite(obuf,1,os-obuf,stdout);os = obuf;}inline void putch(char ch){*os++ = ch;if(os == ot) flush();}inline void putint(int res){static char q[10];if(res==0) putch('0');else if(res < 0){putch('-');res = -res;}int top = 0;while(res){q[top++] = res % 10 + '0';res /= 10;}while(top--) putch(q[top]);}inline void space(bool x){if(!x) putch('\n');else putch(' ');}}inline void read(int &x){int rt = FastIO::getint();x = rt;}inline void print(int x,bool enter){FastIO::putint(x);FastIO::flush();FastIO::space(enter);}/* definitions */const int MAXN = 5e4 + 10;int n,m,d,u[MAXN];int T,prime[MAXN],cnt;bool isprime[MAXN];/* functions */inline long long solve(){long long ans = 0;scanf("%d%d%d",&n,&m,&d);if(n > m) std::swap(n,m);n /= d, m /= d;for(int i=1,j;i <= n;i = j + 1){j = std::min(n / (n / i), m / (m / i));ans += (long long) (u[j] - u[i - 1]) * (n / i) * (m / i);}return ans;}inline void init(){u[1] = 1;FOR(i,2,MAXN,1){if(!isprime[i]) u[i] = -1, prime[++cnt] = i;for(int j=1;j <= cnt && (long long) i * prime[j] <= MAXN;++j){isprime[i * prime[j]] = true;if(i % prime[j] == 0) break;u[i * prime[j]] = -u[i];}u[i] += u[i-1];}}int main(int argc,char *argv[]){init();scanf("%d",&T);while(T--) printf("%lld\n",solve());return 0;}