牛客竞赛 阶乘

https://ac.nowcoder.com/acm/contest/5505/C

暴力做法,从2开始循环质因数,对于每次一个质因数i,看p1当前能分解出多少个,然后再枚举n,看n最小为多少能做到质因数i的数量大于等于p1
代码中有句sum=max(sum,j);什么含义?你想如果我们之前求出n=9包含3的数量满足条件,那枚举5时得到n=10,10的阶乘是包含9的阶乘,也就是10!既满足质因数2也满足3,所以求最大max
代码内也有注释

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int main()
 4 {
 5     int t,p1,sum=0;
 6     cin>>t;
 7     while(t--){
 8         cin>>p1;
 9         sum=0;
10         for(int i=2;i*i<=p1;++i)
11          if(p1%i==0)
12          {
13             int cnt=0;
14             while(p1%i==0)
15             {
16                 p1/=i;
17                 ++cnt;
18             }//当前质因子i在p1中的数量
19             int tmp=0;
20             int j;
21             for(j=i;;j+=i)
22             {
23                      int n=j;
24                     while(n%i==0)
25                     {
26                         n/=i;
27                         ++tmp;
28                     } //记录当前质因数在n中的数量
29  
30                 if(tmp>=cnt) break;//找到一个数,使得他的质因数i的数量多于等于p1
31             }
32             sum=max(sum,j);
33  //           cout<<sum<<endl;
34         }
35         cout<<max(sum,p1)<<endl;
36     }
37 }
View Code

https://blog.nowcoder.net/n/aa5ff9efa80440c897a9aaae4401a467

还有一个二分解法的代码,二分解法的解析在下面的官方题解中

这里我们来说下,在judge代码中,为何是如此计算次数的;

举个例子: 假如mid=8,那么就有1 2 3 4 5 6 7 8这样几个数

      假如现在我们有一个质数为2,让我们计算构成这些数的质数2的个数,计算如下:

         8/2=4,有4个数是2的倍数,将不满足的数字(1,3,5,7)去掉

       再将剩下的数除以2,为1 2 3 4 

      然后重复以上过程,就可以计算出在mid!中,质数2的个数为多少,然后跟满足条件进行比较即可 

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int maxn=1e5;
 4 int p,num[maxn],primer[maxn],k;
 5 bool judge(int x){  //判断函数
 6     for(int i=1;i<=k;i++){
 7         int n=x,num_primer=0;
 8         while(n){
 9             num_primer+=n/primer[i];
10             n/=primer[i];
11         }
12         if(num_primer<num[i])  return false;
13     }
14     return true;
15 }
16 void solve(){
17     k=0;
18     for(int i=2;i*i<=p;i++){  //对质因数进行分解
19         if(p%i==0){
20             primer[++k]=i;  //注意这里是++k
21             while(p%i==0){
22                 num[k]++;
23                 p/=i;
24             }
25         }
26     }
27     if(p>1)  primer[++k]=p,num[k]++;
28     int l=1,r=1e9,ans;
29     while(l<=r){
30         int mid=(l+r)/2;
31         if(judge(mid)){  //如果这时候的mid满足题意,但我们要求的是最小的,所以将区间移到左边,即将右限左移,mid-1
32             r=mid-1;
33             ans=mid;
34         }
35         else  l=mid+1;
36     }
37     memset(num,0,sizeof(num));  //记住,因为这是多组测试,所以要将num数组置为0,以便不会影响下次
38     cout<<ans<<endl;
39 }
40 int main(){
41     int t;
42     cin>>t;
43     while(t--){
44         cin>>p;
45         solve();
46     }
47     return 0;
48 }
View Code

 

这是官方题解()

posted @ 2020-05-03 13:03  古比  阅读(169)  评论(0编辑  收藏  举报