HDU 1695 GCD

这个题要用容斥定理,求出x与y互质的对数,然后x与y同时乘以k,如果x与y都在范围之内,则这一对符合条件;

这里的处理方法就是对b与d缩小k倍,寻找里面的互质的数的对数,我们在扩大k倍,就可以解决,上面存在的问题;

View Code
#include<iostream>

#include<cstdio>

#include<cstdlib>

#include<algorithm>

#include<cmath>

#include<queue>

#include<set>

#include<map>

#include<cstring>

#include<vector>

#include<string>

#define LL long long

using namespace std;

int prime[10000],cnt;

class Node

{

public:

      int num[20];

      int cnt;    

}node[100024];

void Prime( )

{

    bool hash[50025] = {0};

    int t = ( int )sqrt( 100000.0 ) + 1;

    for( int i = 3 ; i <= t ; i += 2 )

    {

        if( hash[i>>1]==false )

        {

            int x = i << 1;

            for( int j = i * i ; j <=100000 ; j += x )

                 hash[j>>1] = true;     

        }

    }

    cnt = 0;

    prime[cnt++] = 2;

    for( int i = 1; i <= 50000 ; i ++ )

    {

         if( hash[i]==false )

         {

             prime[cnt++] = ( i << 1 ) + 1;    

         }    

    }

    for( int i = 1 ; i <= 100000; i ++ )//求质因子 

    {

        t = i;

        node[i].cnt = 0;

        for( int j = 0; j < cnt ; j ++ )

        {

             if( t < prime[j] )    break;

             if( t % prime[j] == 0 )

             {

                  node[i].num[node[i].cnt++] = prime[j];

                  while( t % prime[j] == 0 )

                         t /= prime[j];        

             }

        }    

    }

}

LL DFS( int d , int m , int t )//容斥 

{

   LL ans = 0;

   for( int i = t ; i < node[m].cnt ; i ++ )

   {

        ans += (LL)d/node[m].num[i] - DFS( d/node[m].num[i] , m , i + 1 );        

   }    

   return ans;

}

int main(  )

{

    Prime();

    int a,b,c,d,T,k;

    while( scanf( "%d",&T )==1 )

    {

        for( int l = 1 ; l <= T ; l ++ )

        {

            LL ans = 0;

            scanf( "%d %d %d %d %d",&a,&b,&c,&d,&k );

            printf( "Case %d: ",l );

            if( k == 0 ) printf( "0\n" );

            else

            {

                if( b >= k && d >= k ) ans = 1;

                //把b,d缩小k倍,求所有范围内的互质的数,在扩大k倍之后,一定在原先的范围之内 

                b /= k; d /= k;

                if( b > d ) swap( b ,d );

                for( int i = 1 ; i <= b ; i ++ )

                {

                     int t = d - i ;

                     if( t <= 0 ) break;

                     ans +=(LL) t - DFS( t , i , 0  );    

                }

                printf( "%I64d\n",ans  );

           }

        }

    }

    //system( "pause" );

    return 0;

}

 

你可能感兴趣的:(HDU)