bzoj 2820

 

收获:

当一个东西的取值有限时,我们可以枚举它,然后统计它被计算了多少次。

 

 1 #include <cstdio>
 2 #include <iostream>
 3 using namespace std;
 4 
 5 typedef long long dnt;
 6 
 7 int prm[10000010], isnot[10000010], mu[10000010], f[10000010], ptot;
 8 
 9 void init( int n ) {
10     mu[1] = 1;
11     for( int i=2; i<=n; i++ ) {
12         if( !isnot[i] ) {
13             prm[++ptot] = i;
14             mu[i] = -1;
15         }
16         for( int j=1; j<=ptot && i*prm[j]<=n; j++ ) {
17             isnot[i*prm[j]]=true;
18             if( i%prm[j]==0 ) {
19                 mu[i*prm[j]] = 0;
20                 break;
21             }
22             mu[i*prm[j]] = -mu[i];
23         }
24     }
25     for( int i=1; i<=ptot; i++ ) {
26         int p = prm[i];
27         for( int j=p; j<=n; j+=p )
28             f[j] += mu[j/p];
29     }
30     for( int i=1; i<=n; i++ )
31         f[i] += f[i-1];
32 }
33 dnt calc( dnt n, dnt m ) {
34     if( n>m ) swap(n,m);
35     dnt rt = 0;
36     for( int i=1; i<=n; i++ ) {
37         int ii = min( n/(n/i), m/(m/i) );
38         rt += (f[ii]-f[i-1])*(n/i)*(m/i);
39         i = ii;
40     }
41     return rt;
42 }
43 int main() {
44     int T;
45     init( 10000000 );
46     scanf( "%d", &T );
47     while( T-- ) {
48         int n, m;
49         scanf( "%d%d", &n, &m );
50         printf( "%lld\n", calc(n,m) );
51     }
52 }
View Code

 

posted @ 2015-03-30 20:37  idy002  阅读(112)  评论(0编辑  收藏  举报