bzoj 2693
收获:
1、积性函数的积也是积性函数,基本的积性函数:常数函数,正比例函数,欧拉函数,Mobius函数,积性函数一般都知道表达式,所以一般都可以在线性筛时搞定。
2、遇到整除求和时,这个东西就已经是最简了,所以可以考虑提出它,然后尝试搞后边的东西的前缀和,如果可以成功,那么就可以在O(sqrt(n))的复杂度做了。
1 /************************************************************** 2 Problem: 2693 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:4692 ms 7 Memory:118504 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <iostream> 12 #define M 100000009 13 using namespace std; 14 15 typedef long long dnt; 16 17 int prm[10010], isnot[10000010], mu[10000010], dm[10000010], ptot; 18 19 void init( int n ) { 20 mu[1] = 1; 21 dm[1] = 1; 22 for( int i=2; i<=n; i++ ) { 23 if( !isnot[i] ) { 24 prm[++ptot] = i; 25 mu[i] = -1; 26 dm[i] = (dnt)i*(1-i) % M; 27 } 28 for( int j=1; j<=ptot && i*prm[j]<=n; j++ ) { 29 int k = i*prm[j]; 30 isnot[k] = true; 31 if( i%prm[j]==0 ) { 32 mu[k] = 0; 33 dm[k] = (dnt)k/i*dm[i] % M; 34 break; 35 } 36 mu[k] = -mu[i]; 37 dm[k] = (dnt)dm[i]*dm[prm[j]] % M; 38 } 39 } 40 for( int i=1; i<=n; i++ ) { 41 dm[i] += dm[i-1]; 42 if( dm[i]>=M ) dm[i]-=M; 43 if( dm[i]<0 ) dm[i]+=M; 44 } 45 } 46 inline dnt S( dnt n, dnt m ) { 47 return ((1+n)*n/2%M) * ((1+m)*m/2%M) % M; 48 } 49 dnt calc( int n, int m ) { 50 if( n>m ) swap(n,m); 51 dnt rt = 0; 52 for( dnt d=1; d<=n; d++ ) { 53 dnt dd = min( n/(n/d), m/(m/d) ); 54 rt += S(n/d,m/d) * (dm[dd]-dm[d-1]) % M; 55 if( rt>=M ) rt-=M; 56 if( rt<0 ) rt+=M; 57 d = dd; 58 } 59 return rt; 60 } 61 int main() { 62 init(10000000); 63 int T; 64 scanf( "%d", &T ); 65 while( T-- ) { 66 int n, m; 67 scanf( "%d%d", &n, &m ); 68 printf( "%lld\n", calc(n,m) ); 69 } 70 }