歡迎訪問我的新博客:http://www.milkcu.com/blog/
原文地址:http://www.milkcu.com/blog/archives/uva10139.html
原創:
作者:MilkCu
題目描述
Problem D: Factovisors
The factorial function, n! is defined thus for n a non-negative integer:0! = 1 n! = n * (n-1)! (n > 0)We say that a divides b if there exists an integer k such that
k*a = bThe input to your program consists of several lines, each containing two non-negative integers, n and m, both less than 2^31. For each input line, output a line stating whether or not m divides n!, in the format shown below.
Sample Input
6 9 6 27 20 10000 20 100000 1000 1009
Output for Sample Input
9 divides 6! 27 does not divide 6! 10000 divides 20! 100000 does not divide 20! 1009 does not divide 1000!
解題思路
思路比較流暢,依次求2~n之間的數與m的最大公約數,然後用公約數去除m。
若m能被除盡,則m可以整除n!;否則不能。
但是提交到UVaOJ爲什麼會超時呢?看來還需要優化。
如果在遍歷2~n之間的數時,遇到的數i爲質數。
若m爲素數且m>n,則m與2~n中的任何數互素。
其他優化:把開方放在循環外邊。
從n到2遞減尋找最大公約數可以提高效率。
還要注意特殊情況的處理。
PC可以通過,UVaOJ總是超時,太浪費時間了。
對於我的不高的要求,以後使用PC吧。
兩種求最大公約數的方法:
1. 遞歸
int gcd(int a, int b) {
if(b == 0) {
return a;
}
if(a < b) {
return gcd(b, a);
}
return gcd(b, a % b);
}
2. 循環
int gcd(int a, int b) {
if(a < b) {
int tmp = a;
a = b;
b = tmp;
}
while(b > 0) {
int tmp = a;
a = b;
b = tmp % b;
}
return a;
}
代碼實現
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
int isPrime(int x) {
int sq = sqrt(x);
for(int i = 2; i <= sq; i++) {
if(x % i == 0) {
return 0;
}
}
return 1;
}
int gcd(int a, int b) {
if(a < b) {
int tmp = a;
a = b;
b = tmp;
}
while(b > 0) {
int tmp = a;
a = b;
b = tmp % b;
}
return a;
}
int main(void) {
int n, m;
while(cin >> n >> m) {
if(m == 0) {
cout << m << " does not divide " << n << "!" << endl;
continue;
}
if(m == 1) {
cout << m << " divides " << n << "!" << endl;
continue;
}
if(isPrime(m) && m > n) {
cout << m << " does not divide " << n << "!" << endl;
continue;
}
int tm = m;
for(int i = n; i >= 2; i--) {
int g = gcd(i, tm);
if(g > 1) {
//cout << i << " " << g << endl;
tm /= g;
}
if(tm == 1) {
cout << m << " divides " << n << "!" << endl;
break;
}
}
if(tm != 1) {
cout << m << " does not divide " << n << "!" << endl;
}
}
return 0;
}
(全文完)