hdu--5072--容斥原理

tmd还是自己没做出拿牌题。。。

可以看下别人的博客 有很详细的解释

但我自己开始没想出来 cao......

其实 这个思路不算特别难的 和我这几天遇到的dp题相比

注意下 hash[ i ]表示给定的n个数中是 i 的倍数的数有几个

要注意下 n * (n-1) * (n-2 ) / 6会超Int整数上限 我TMD的就在那边折腾了半小时 ...

  1 #include <iostream>
  2 #include <cstring>
  3 #include <vector>
  4 using namespace std;
  5 
  6 typedef __int64 LL;
  7 int num;
  8 LL n;
  9 const int size = 100000;
 10 int a[size+10];
 11 bool flag[size+10];    
 12 bool vis[size+10];
 13 int prime[size+10];
 14 int hash[size+10];
 15 vector<int>ve[size+10];
 16 
 17 void init( )
 18 {
 19     num = 0;
 20     memset( vis , true , sizeof(vis) );
 21     vis[0] = vis[1] = false;
 22     for( int i = 2 ; i<=size ; i++ )
 23     {    
 24         if( vis[i] )
 25         {
 26             prime[ num++ ] = i;
 27             int j = i * 2;
 28             while( j<=size )
 29             {
 30                 vis[j] = false;
 31                 j += i;
 32             }
 33         }
 34     }
 35 }
 36 
 37 void fenjie( int y , int x )
 38 {
 39     ve[y].clear( );
 40     for( int i = 0 ; i<num&&prime[i]*prime[i]<=x ; i++ )
 41     {
 42         if( x%prime[i]==0 )
 43         {
 44             ve[y].push_back( prime[i] );
 45             while( x%prime[i]==0 )
 46             {
 47                 x /= prime[i];
 48             }
 49         }
 50     }
 51     if( x>1 )
 52     {
 53         ve[y].push_back( x );//将x分解出来的话 会有多少个质因子
 54     }
 55 }
 56 
 57 LL solve( )
 58 {
 59     for( int i = 2 ; i<=size ; i++ )
 60     {
 61         for( int j = i ; j<=size ; j+=i )
 62         {
 63                 if( flag[j] )
 64                     ++ hash[i];
 65         }
 66     }
 67     LL ans = 0;
 68     LL var , sum;
 69     int cnt , veSize;
 70     for( int i = 0 ; i<n ; i++ )
 71     {
 72         veSize = ve[i].size();
 73         sum = 0;
 74         for( int j = 1 ; j<( 1<<veSize ) ; j++ )
 75         {        
 76             cnt = 0;
 77             var = 1;
 78             for( int k = 0 ; k<veSize ; k++ )
 79             {
 80                 if( j&(1<<k) )
 81                 {
 82                     ++ cnt;
 83                     var *= (LL) ve[i][k];
 84                 }
 85             }
 86             if( cnt&1 )//奇加偶减
 87             {
 88                 sum += hash[var];
 89             }
 90             else
 91             {
 92                 sum -= hash[var];
 93             }
 94         }
 95         if( sum==0 )// sum   与a[i]非 互质的个数 
 96             continue;
 97         ans += (LL)( (sum-1) * ( n-sum ) );
 98     }
 99     return ans/2;
100 }
101 
102 int main()
103 {
104     cin.sync_with_stdio(false);
105     init( );
106     int t;
107     LL ans;
108     cin >> t;
109     while( t-- )
110     {
111         memset( hash , 0 , sizeof(hash) );
112         memset( flag , false , sizeof(flag) );
113         cin >> n;
114         for( int i = 0 ; i<n ; i++ )
115         {
116             cin >> a[i];
117             flag[ a[i] ] = true;    
118             fenjie( i , a[i] );
119         }
120         ans = solve( );
121         ans = (LL)( n*(n-1)*(n-2)/6 - ans );
122         cout << ans << endl; 
123     }
124     return 0;
125 }
View Code
原文地址:https://www.cnblogs.com/radical/p/4115327.html