Test instructions: 1<=x<=n,1<=y<=m, which causes gcd (x, y) =k,k to be less than or equal to the number of P
Example: 24=2*2*2*3,k=4
Solution: Set F[n] to GCD (A, b) =n logarithm
F[d] is the logarithm of D|GCD (A, B)
F[n]=sigema (Mu[i],f[i*n]):
F[1]=mu[1]*f[1]+mu[2]*f[1*2]+...+mu[n]*f[1*n]
F[2]=mu[2]*f[2]+mu[2]*f[2*2]+...+mu[n]*f[2*n]
......
Sum=f[1]+f[2]+...+f[n]=g[1]*f[1]+g[2]*f[2]+...+g[n]*f[n]
Enumerate each I, then the multiples of I J for G[j] provide the contribution of mu[j/i], i.e. g[j]+=mu[j/i]
Because the number of the g[j to be K is the result of several numbers, it is opened to a two-dimensional array g[j][p] to represent the contribution of J to the number of p.
Need to use the method of block acceleration, or it will explode
#include <stdio.h> #include <string.h> #define MIN (a) (a) < (b)? A):(B)) #define MAX (a) < (b) ( b):(a)) #define LL __int64const int maxn=500005;int num[maxn];int prime[maxn];int mu[maxn];int factor[maxn];int MBS[MAXN ][20];void Mobius () {memset (num,0,sizeof (num)); int all=0; Mu[1]=1; factor[1]=0; for (int i=2;i<maxn;i++) {if (!num[i]) {prime[all++]=i; Mu[i]=-1; Factor[i]=1; The record is a number of characters} for (int j=0;j<all&&i*prime[j]<maxn;j++) {num[i*prime[j]]=1; factor[i*prime[j]]=factor[i]+1; if (I%prime[j]) {mu[i*prime[j]]=-mu[i]; } else {mu[i*prime[j]]=0; Break }}} return;} void Inti () {memset (mbs,0,sizeof (MBS)); for (int i=1;i<maxn;i++) for (int j=i;j<maxn;j+=i) MBS[J][FACTOR[I]]+=MU[J/I]; Contribution of each J in Factor[i] factors
/* The following is for block acceleration summation * /for (int i=1;i<maxn;i++) for (int j=0;j<19;j++) mbs[i][j]+=mbs[i-1][j];
for (int. i=0;i<maxn;i++) for (int j=1;j<19;j++) mbs[i][j]+=mbs[i][j-1]; return;} int main () { int t,n,m,p; Mobius (); Inti (); ll sum; while (scanf ("%d", &t)!=-1) {while (t--) { scanf ("%d%d%d", &n,&m,&p); if (p>=19) //Because 2^19>500000, so more than 19 is all meet the requirements { printf ("%i64d\n", (ll) n*m); Continue; } if (n>m) { int te=n; n=m; M=te; } sum=0; for (int i=1,last;i<n;i=last+1) { last=min (n/(n/i), m/(m/i));
Block acceleration, because [n/i][m/i] has a repeating part in the I sliding scale process, skipping these I but simplifying the calculation, is the complexity reduced to sqrt (n) sum+= ((LL) (n/i) * (m/i) * (mbs[last][p]-mbs[i-1][p ])); } printf ("%i64d\n", sum); } } return 0;}
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
HDU 4746 mophues Möbius third bomb