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 }