HDU 1695&4135 容斥

【題目鏈接】
http://acm.hdu.edu.cn/showproblem.php?pid=4135

http://acm.hdu.edu.cn/showproblem.php?pid=1695

【解題報告】
題目其實很簡單,考慮到容斥需要的幾個基本操作需要打熟練,就更新這麼一篇blog上來。

hdu4135很裸。給出一個N,求A,B區間內和N互素的數都個數。那麼我們如果知道有多少數和N不互質,取個反就ok了。所以把N**質因數分解**(其實我第一遍質因數分解寫錯了,所以T了一發,讀者應該敲熟質因數分解,儘量避免手殘現象的出現),求A,B之間以N的質因數爲約數的數的總個數即可。這個過程可以用容斥求得,過程不再贅述。

hdu1695同樣很裸,求兩個區間A..B和C..D之間GCD爲k的數對的個數,注意數對無序所以形似(5,7)和(7,5)的數對被認爲是一個數對。
假設GCD(x,y)=k,其實我們只需要知道kGCD(x’,y’)=1的數對有多少個即可。要注意一點即kx’ in a..b; ky’ in c..d。
尤其注意,a和c已限定爲1.

【參考代碼:4135】

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;

typedef long long LL;

vector<LL>P;
LL N,A,B;
void getphi(  LL N )
{
      P.clear();
      int k=2;
      while( k*k<=N )
      {
            if(  N%k==0  )
            {
                  P.push_back( k );
                  while( N%k==0  )N/=k;
            }
            k++;
      }
      if(  N>1 )P.push_back(  N );
}

int GCD( int A, int B  )
{
      if(  B==0 )return A;
      else return GCD(  B,A%B  );
}

int LCM(  int A, int B )
{
      return A*B/GCD( A,B  );
}

LL solve()
{
      int L=P.size();
      LL ans=0;
      for(  int i=1;i<(1<<L); i++   )
      {
            int cur=0,num=1;
            for(  int j=L-1; j>=0;j-- )if(   (1<<j)&i  )
            {
                  num=LCM(  num,P[j]   );
                  cur++;
            }
            if( cur&1 ) ans+=(LL)B/num-(LL)(A-1)/num;
                  else ans-=(LL)B/num-(LL)(A-1)/num;
      }
      return (LL)B-(LL)A+1LL-ans;
}

void swaps(  LL& A, LL& B ) { LL tmp=A; A=B; B=tmp; }

int main()
{
      int T,kase=0; cin>>T;
      while( T-- )
      {
            cin>>A>>B>>N;
            if(  A>B )swaps(  A,B );
            getphi( N );
           // if( N==1 )P.push_back( 1 );
          //  for( int i=0; i<P.size(); i++  )cout<<P[i]<<endl;
            cout<<"Case #"<<++kase<<": "<<solve()<<endl;
      }

      return 0;
}

【參考代碼:1695】

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
using namespace std;

typedef long long LL;

int a,b,c,d,k;
LL ans;
vector<int>P;

void getphi( int n )
{
      P.clear();
      int k=2;
      while( k*k<=n ){
            if(  n%k==0 ){
                  P.push_back( k );
                  while( n%k==0 )n/=k;
            }
            k++;
      }
      if(  n>1 )P.push_back(n);
}

int GCD( int x, int y ){ return y ? GCD(y,x%y) : x;  }
int LCM( int x, int y ) { return x*y/GCD(x,y); }

LL solve()
{
      LL ans=0;
      for( int i=1; i<=b; i++ )
      {
            getphi(i);
            int m=P.size();
            for(  int j=1; j<(1<<m); j++ )
            {
                  int cur=0,num=1;
                  for(  int k=0; k<m; k++  )if( (1<<k)&j )
                  {
                        num=LCM(num,P[k]);
                        cur++;
                  }
                  if( cur&1 )ans+=d/num-(i-1)/num;
                        else ans-=d/num-(i-1)/num;
            }
      }
      return (LL)(d*2-b+1)*b/2-ans;
}

//d+d-1+...+(d-b+1)   (d*2-b+1)b/2

int main()
{
      int T,kase=0; scanf( "%d",&T );
      while(  T-- )
      {
            scanf( "%d%d%d%d%d",&a,&b,&c,&d,&k );
            if(k==0){
                  printf( "Case %d: %lld\n",++kase,0 );
                  continue;
            }
            b/=k; d/=k;
            if( b>d ) swap(b,d);
            printf(  "Case %d: %lld\n",++kase, solve( ));
      }
      return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章