HDU 1299 Diophantus of Alexandria

x 、y、n都是正整数,并且 显然,x >= n , y >= n ,现在假设 y = n +k (k为正整数) ,那么带入公式,可以得出 x = (n*(n+k))/k = n*n/k + n; 由于x 是正整数,现在的关键问题就是要求出 n*n/ k 有多少组正整数的可能,显然,所要求的就是 n*n 因子的个数// 问题已经非常接近答案了,但是最后还有一个问题,n<= 10^9 , 那么n*n <= 10^18 ,对于一个这么大的数字怎样才能求出它因子的个数呢?

命题1: 一个正整数 n 可以用素因子唯一表示为 p1^r1 * p2^r2 * ... pk^rk (其中 pi 为素数) , 那么这个数的因子的个数就是,(r1+1)*(r2+1)*...*(rk+1).

如果一个数字 n = p1^r1 * p2^r2 * ... pk^rk ,那么 n*n = p1^r1 * p2^r2 * ... pk^rk * p1^r1 * p2^r2 * ... pk^rk ,它的因子的个数就是 (2*r1+1)*(2*r2+1)*...*(2*rk+1).

由1/x+1/y=1/n
  简化成(x-n)(y-n)=n*n,
  
  很明显,只要能将n*n进行因数分解,
  则其解都满足题意。
  
  假设n可写成:
  a1^k1 * a2^k2 * a3^k3 * ... * am^km, (1)
  其中a1,a2,a3,...am互质,
  则n*n的约数为
  (2k1+1)(2k2+1)(2k3+1)...(2km+1), (2)
  记其积为O,
  从而其存在的解的个数为
  [O+1]/2,

#include<stdio.h>
#include<stdlib.h>
int  prime(  int num[] )//素数筛选
{
     int hash[20000]={0};
     for( int i=3; i<=200; i+=2 )
     {
         if( hash[i/2] )
           continue;
           int x=i<<1;
         for( int j=i*i; j<40000; j+=x )
            hash[j/2]=1;     
     }   
     int count=0;
     num[++count]=2;
     for( int i=1; i<20000; i++ )
     {
           if( hash[i]==0 ) 
           num[++count]=(i<<1)+1;    
     }
     return count;
}
int res( int num[], int count ,int  number )
{
    int sum=1;
    for( int i=1; i<=count; i++ )
    {
         if( number==1 ) break;
        int x=0;
        while( number%num[i]==0 )
        {
           x++;
           number/=num[i];       
        }     
        sum*=(2*x+1);
    }
    if( number!=1 )
       sum*=3;
    return sum;    
}
int main()
{
    int n,num[5000],number;
    int count=prime( num );
    scanf( "%d",&n );
    for( int i=1; i<=n; i++ )
    {
        scanf( "%d",&number );
        printf( "Scenario #%d:\n" ,i);
        printf( "%d\n",(res( num,count,number )+1)/2  );
        puts("");     
    }
    return 0;    
}

  

posted @ 2011-08-16 11:29  wutaoKeen  阅读(383)  评论(0编辑  收藏  举报