bzoj 1101

 

其实这个用的是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 }
View Code

 

posted @ 2015-03-31 19:33  idy002  阅读(194)  评论(0编辑  收藏  举报