5791. 【NOIP2008模拟】阶乘
(File IO): input:factorial.in output:factorial.out
Time Limits: 1000 ms Memory Limits: 262144 KB Detailed Limits
做法:
View Code
题目要求一个最小的m使m!包含p这个因子。
可以把p分解质因数,假设p=∏ai^bi(ai为质数),那么只要m!包含了每个ai^bi,m!就包含p。
所以对于每个ai^bi,分别求出满足条件的最小的m,取最大值即可。
怎么求m?
先看一个简单的问题:
27!里面有多少个3相乘?
27!=1*2*...*27
包含1个3的数有27/(3^1)=9个
包含2个3的数有27/(3^2)=3个
包含3个3的数有27/(3^3)=1个
总共:9+3+1=13个
所以27!里面有13个3相乘。
用这个方法就可以求得m!有多少个ai相乘,二分判断即可。
代码如下:
1 #include <cstdio> 2 #include <iostream> 3 #include <cstring> 4 #define LL long long 5 #define N 600007 6 using namespace std; 7 LL n, zs[N], T, a[N]; 8 LL tot = 1, ans; 9 bool b[N]; 10 11 void Pre_work() 12 { 13 for (int i = 2; i <= N / 2; i++) 14 { 15 if (!b[i]) 16 { 17 zs[++zs[0]] = i; 18 for (int j = 1; j <= zs[0]; j++) 19 if (i * zs[j] > N / 2) break; 20 else b[zs[j] * i] = 1; 21 } 22 else 23 { 24 for (int j = 1; j <= zs[0]; j++) 25 if (i * zs[j] > N / 2) break; 26 else b[zs[j] * i] = 1; 27 } 28 } 29 } 30 31 LL max(LL a, LL b) 32 { 33 return a > b ? a : b; 34 } 35 36 void Cl(LL x) 37 { 38 for (int i = 1, p = x; p > 1; i++) 39 for (; p % zs[i] == 0; p /= zs[i]) 40 { 41 if (!b[p]) 42 { 43 a[p]++; 44 T = max(T, p); 45 p = 1; 46 break; 47 } 48 a[zs[i]]++, T = max(T, zs[i]); 49 } 50 } 51 52 bool Check(LL ain) 53 { 54 for (int i = 1; i <= T; i++) 55 { 56 int j = zs[i]; 57 LL Jl = 0; 58 for (LL k = j; (k <= ain) && (Jl < a[zs[i]]); k *= j) Jl += ain / k; 59 if (Jl < a[zs[i]]) return 0; 60 } 61 return 1; 62 } 63 64 void Find() 65 { 66 LL l = 1, r = 100000000; 67 while (l < r) 68 { 69 LL mid = (l + r) / 2; 70 if (Check(mid)) r = mid; 71 else l = mid + 1; 72 } 73 printf("%lld", l); 74 } 75 76 int main() 77 { 78 freopen("factorial.in", "r", stdin); 79 freopen("factorial.out", "w", stdout); 80 scanf("%lld", &n); 81 LL x; 82 Pre_work(); 83 for (int i = 1; i <= n; i++) 84 { 85 scanf("%lld", &x); 86 if (!b[x]) 87 { 88 a[x]++, T = max(T, x); 89 continue; 90 } 91 Cl(x); 92 } 93 Find(); 94 }