bzoj 2154

 

收获:

  1、当一个东西的取值范围很小时,或者感觉它很麻烦时,就枚举它

  2、熟悉mobius函数、euler函数的和函数,以及euler函数用mobius函数的表示。

  3、下取整分块理解更深了。

 

 1 /**************************************************************
 2     Problem: 2154
 3     User: idy002
 4     Language: C++
 5     Result: Accepted
 6     Time:5584 ms
 7     Memory:157916 kb
 8 ****************************************************************/
 9  
10 #include <cstdio>
11 #include <iostream>
12 #define M 20101009
13 using namespace std;
14  
15 typedef long long dnt;
16  
17 int prm[100000], isnot[10000010], mu[10000010], ptot;
18 dnt mds[10000010];
19  
20 void init( int n ) {
21     mu[1] = 1;
22     for( int i=2; i<=n; i++ ) {
23         if( !isnot[i] ) {
24             prm[++ptot] = i;
25             mu[i] = -1;
26         }
27         for( int j=1; j<=ptot && i*prm[j]<=n; j++ ) {
28             isnot[i*prm[j]] = true;
29             if( i%prm[j]==0 ) {
30                 mu[i*prm[j]] = 0;
31                 break;
32             }
33             mu[i*prm[j]] = -mu[i];
34         }
35     }
36     for( dnt d=1; d<=n; d++ ) {
37         mds[d] = (mu[d]*d*d)%M;
38         mds[d] += mds[d-1];
39         if( mds[d]>=M ) mds[d]-=M;
40         if( mds[d]<0 ) mds[d]+=M;
41     }
42 }
43  
44 inline dnt S( dnt x, dnt y ) {
45     return (((1+x)*x/2%M)*(((1+y)*y)/2%M)%M);
46 }
47 dnt F( dnt x, dnt y ) {
48     if( x>y ) swap(x,y);
49     dnt rt = 0;
50     for( dnt d=1; d<=x; d++ ) {
51         dnt dd = min( x/(x/d), y/(y/d) );
52         rt += S(x/d,y/d) * (mds[dd]-mds[d-1]) % M;
53         if( rt<0 ) rt += M;
54         if( rt>=M ) rt -= M;
55         d = dd;
56     }
57     return rt;
58 }
59 dnt calc( dnt n, dnt m ) {
60     if( n>m ) swap(n,m);
61     dnt rt = 0;
62     for( dnt d=1; d<=n; d++ ) {
63         dnt dd=min( n/(n/d), m/(m/d) );
64         rt += ((d+dd)*(dd-d+1)/2 % M) * F( n/d, m/d ) % M;
65         if( rt<0 ) rt+=M;
66         if( rt>=M ) rt-=M;
67         d = dd;
68     }
69     return rt;
70 }
71 int main() {
72     int n, m;
73     scanf( "%d%d", &n, &m );
74     if( n>m ) swap(n,m);
75     init(n);
76     printf( "%lld\n", calc(n,m) );
77 }
View Code

 

posted @ 2015-03-31 16:28  idy002  阅读(199)  评论(0编辑  收藏  举报