zoukankan      html  css  js  c++  java
  • JZOJ 5791. 【NOIP2008模拟】阶乘

    Description

    有n个正整数a[i],设它们乘积为p,你可以给p乘上一个正整数q,使p*q刚好为正整数m的阶乘,求m的最小值。
     

    Input

    共两行。
    第一行一个正整数n。
    第二行n个正整数a[i]。

    Output

    共一行
    一个正整数m。
     

    Sample Input

    1
    6

    Sample Output

    3
    
    样例解释:
    当p=6,q=1时,p*q=3!
     
     

    Data Constraint

    对于10%的数据,n<=10
    对于30%的数据,n<=1000
    对于100%的数据,n<=100000,a[i]<=100000
     
     
    做法:

    题目要求一个最小的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 }
    View Code
  • 相关阅读:
    c#中将IP地址转换成无符号整形数的方法与逆变换方法
    中英文字符的截取
    c#读取并分析sql Server2005数据库日志
    枚举enum使用
    LINQ to XML 编程基础
    c#异步调用的几种方式
    File,FileInfo,FileStream,StreamReader的区别与用法
    Page.ClientScript.RegisterStartupScript用法小结
    asp.net图片上传及删除
    FileUpload控件
  • 原文地址:https://www.cnblogs.com/traveller-ly/p/9461939.html
Copyright © 2011-2022 走看看