TOJ 1537


題目連接:

http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=1537


題目類型:

數學 - 數論 - 最大公約數


數據結構:


思路分析:

-----------------------------------------------------------------

形如 X1/X2/X3/..../Xk 式子

利用加括號的方式讓它等於一個整數

則可以知道 X1 必爲分子, X2 必爲分母

另外可以得出, 除X2外, 另其他數字全爲分子, 則有最大機率得出整出

最後X2單獨作爲分母,

只需讓分子上的數除盡X2 最後便是整數,

反之不是整數


兩種方法

1.-------------------------------------------------------------------------

將X2分解質因子

去除所有的分子,

如果能吧所有的質因子約完,

則能得出整數

2.-------------------------------------------------------------------------

讓分子裏的所有數都挨個除以它和X2的最大公約數

如果到最後之前能另X2爲1

則是YES

否則是NO


證明:

方法1:

因爲Xi 是不大於2000000000的數字

所以它的質因子範圍可能有2~sqrt(2000000000) =45000  之多,

最大可能個數接近於10 個 (2*3*5....) < 2000000000

所以首先要列舉所有可能的質數,

從2開始遍歷到45000 找到所有n可能的質因子,

另外要注意的是有可能篩選到 sqrt(n) 的時候 並未列舉所有的質因子,

因爲有可能有因子 n / 2 > x > sqrt( n )

則那個剩餘的數必定是質數 且 只有一個

所以只要列舉即可.


方法2:

不進行質因子分解.

直接將X2與各個分子進行相除

分子最大有K-1=9999個

每個分子最大不超過2000000000

設 Xi 與 X2 接近於 2000000000

他們要做最大公約數的運算

運算次數都是在 30以內;



源代碼:

方法1:

#include <stdio.h>
#include <iostream>
#include <string>

using namespace std;

bool tese[32005] = { false };
__int64 prime[3500],
		divir[15][2],
		prime_snt = 2;
__int64 arr[10005];

/******************************
		判斷素數
*******************************/
void _getprime()
{
	int i, j;
	
	for( i = 2; i < 32000; i ++ )
	{
		if( !tese[i] )
		{
			prime[ prime_snt ++ ] = i;
			
			for( j = i; i * j < 32000; j ++ )
			{
				tese[i * j] = true;
			}	
		}	
	}
}

/******************************
 將字符串根據'/'拆分成整型數組
 參數1:字符串
 參數2:存儲分解後的整數
 返回:整數個數
*******************************/
int _split( string s, __int64 * ar )
{
	int i, snt = 1;
	__int64 tmp = 0;

	for( i = 0; i < s.length(); i ++ )
	{
		if( s[i] == '/' )
		{
			if( tmp )
			{
				ar[snt ++] = tmp;
				tmp = 0;
			}
		}
		else
		{
			tmp *= 10;
			tmp += ( s[i] - '0' );
		}
	}

	if( tmp )
	{
		ar[snt ++] = tmp;
		tmp = 0;
	}

	return snt - 1;
}

/*******************************************
 對K2質因子分解
 參數1:整型值
 參數2:用於存儲質因子以及個數的二維數組
 返回:不同質因子的個數
********************************************/
__int64 _factor( __int64 r, __int64 dir[15][2] )
{
	__int64 i, snt = 1;

	for( i = 2; i * i <= r && i < prime_snt; i ++ )
	{
		if( r % prime[i] == 0 )
		{
			divir[snt][0] = prime[i];
			divir[snt][1] = 0;

			while( r % prime[i] == 0 )
			{
				r /= prime[i];
				divir[snt][1] ++;
			}

			snt ++;
		}
	}
	
	if( r != 1 )
	{
		divir[snt][0] = r;
		divir[snt][1] = 1;
		snt ++;
	}
	
	return snt - 1;
}

int main()
{
	int i, j;

	_getprime();

	////////////////////////////////////////////////////

	int k, m;
	string str;
	
	while( cin >> str )
	{
		k = _split( str, arr );

		if( k == 1 )
		{
			puts( "YES" );
			continue;
		}

		swap( arr[1], arr[2] );

		m = _factor( arr[1], divir );

		for( i = 1; i <= m; i ++ )
		{
			for( j = 2; j <= k; j ++ )
			{
				while( arr[j] % divir[i][0] == 0 && divir[i][1] > 0 )
				{
					arr[j] /= divir[i][0];
					divir[i][1] --;
				}

				if( divir[i][1] == 0 )
				{
					break;
				}
			}
		}

		int rlt = 0;

		for( i = 1; i <= m; i ++ )
		{
			if( divir[i][1] )
			{
				rlt = 1;
				break;
			}
		}

		if( rlt )
		{
			puts( "NO" );
		}
		else
		{
			puts( "YES" );
		}
	}

	return 0;
}



方法2:

#include <stdio.h>
#include <iostream>
#include <string>

using namespace std;

char str[20000];
__int64 arr[10005];

/******************************
 將字符串根據'/'拆分成整型數組
 參數1:字符串
 參數2:存儲分解後的整數
 返回:整數個數
*******************************/
int _split( char * s, __int64 * ar )
{
	int i, len = strlen( s ), snt = 1;
	__int64 tmp = 0;

	for( i = 0; i < len; i ++ )
	{
		if( s[i] == '/' )
		{
			if( tmp )
			{
				ar[snt ++] = tmp;
				tmp = 0;
			}
		}
		else
		{
			tmp *= 10;
			tmp += ( s[i] - '0' );
		}
	}

	if( tmp )
	{
		ar[snt ++] = tmp;
		tmp = 0;
	}

	return snt - 1;
}

/************************
	  最大公約數
*************************/

__int64 _gcd( __int64 u ,__int64 v )
{
    int re= u % v; 

    while(re) 
	{
		u = v;
		v = re;
		re = u % v; 
	}

    return v;
}

int main()
{
	int i, j;
	int k, m, rlt = 0;
	
	while( scanf( "%s", str ) != EOF )
	{
		rlt = 0;

		k = _split( str, arr );

		if( k == 1 )
		{
			puts( "YES" );
			continue;
		}

		swap( arr[1], arr[2] );

		for( i = 2; i <= k; i ++ )
		{
			__int64 g = _gcd( arr[i], arr[1] );

			arr[i] /= g;
			arr[1] /= g;

			if( arr[1] == 1 )
			{
				rlt = 1;
			}
		}

		if( !rlt )
		{
			puts( "NO" );
		}
		else
		{
			puts( "YES" );
		}
	}

	return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章