欢迎访问我的新博客: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; }
(全文完)