其实这个用的是Mobius反演的第二种形式
F(d) = (n div d) * (m div d)
f(d) = [ gcd(i,j)=d ] (i in [1,a], j in [1,b])
1 /************************************************************** 2 Problem: 1101 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:6764 ms 7 Memory:1688 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <iostream> 12 using namespace std; 13 14 typedef long long dnt; 15 16 int prm[6000], isnot[50010], mu[50010], ptot; 17 18 void init( int n ) { 19 mu[1] = 1; 20 for( int i=2; i<=n; i++ ) { 21 if( !isnot[i] ) { 22 prm[++ptot] = i; 23 mu[i] = -1; 24 } 25 for( int j=1; j<=ptot && i*prm[j]<=n; j++ ) { 26 isnot[i*prm[j]] = true; 27 if( i%prm[j]==0 ) { 28 mu[i*prm[j]] = 0; 29 break; 30 } 31 mu[i*prm[j]] = -mu[i]; 32 } 33 } 34 for( int i=1; i<=n; i++ ) 35 mu[i] += mu[i-1]; 36 } 37 dnt calc( int n, int m, int k ) { 38 dnt rt = 0; 39 if( n>m ) swap(n,m); 40 n/=k; 41 m/=k; 42 for( int d=1; d<=n; d++ ) { 43 int dd=min(n/(n/d),m/(m/d)); 44 rt += (dnt)(n/d)*(m/d)*(mu[dd]-mu[d-1]); 45 d=dd; 46 } 47 return rt; 48 } 49 int main() { 50 init(50000); 51 int T; 52 scanf( "%d", &T ); 53 while( T-- ) { 54 int n, m, k; 55 scanf( "%d%d%d", &n, &m, &k ); 56 printf( "%lld\n", calc(n,m,k) ); 57 } 58 }
时间: 2024-10-12 18:16:56