階乘 (牛客小白月賽23)

題目傳送門

題目描述

給定一個正整數 p
求一個最小的正整數 n,使得 n! 是 p 的倍數

輸入描述:
第一行輸入一個正整數T表示測試數據組數
接下來T行,每行一個正整數p

輸出描述:

輸出T行,對於每組測試數據輸出滿足條件的最小的n。

示例1
輸入

4
1
2
4
8

輸出

1
2
4
4

題解:這道題說的很明白,這裏用二分法進行求解,這裏我們把p分解成質因子的冪相乘的形式p=p1a1*p2a2*p3a3....pkak
,因此我們只要找出一個數滿足所有p中每個質因子出現的次數小於這個數用唯一分解定理分解之後,每個質因子出現的次數即可。因爲我們要求的數是階乘的形式,所以在計算質因子出現的個數的時候要這樣計算,舉個例子假如要計算8的階乘中 2這個因子分解的次數,這裏我們就這樣理算,因爲8的階乘裏面能整除2的數有 2 4 6 8,四個,除以2之後1-4之內是2的倍數的數有2 4兩個,再除2之後1-2之內2的倍數的數有1個,所以這裏一共有4+2+1=7個,

bool check(int x)//判斷這個數是否滿足條件
{
   
    for(int i=1;i<=k;i++)//k是p的所有質因子數
    {
      int primernum=0,n=x;//primernum是判斷的這個數,有幾個prime[i]這個質因子數
      while(n)
      {
      primernum+=n/prime[i];//計算階乘中有幾個此時的質因子
        n/=prime[i];
      }
      if(primernum<num[i])return false;//如果某個質因子在x中的分解出來的次數小於在p中出現的次數,那麼說明不符合條件
    }
    return true;//執行到這一步表示符合條件
}

下面是唯一分解定理求出p的所有質因子,並求出每個質因子出現的次數。

for(int i=2;i*i<=p;i++)
  {
      if(p%i==0)
      {
          prime[++k]=i;
          while(p%i==0)
          {
            num[k]++;
            p/=i;
          }
      }
  }
  if(p>1) prime[++k]=p,num[k]++;

這個時候我們已經把p用埃氏篩進行分解,每個質因子的個數也都已經求出來了,這個時候我們只需要對x就行二分即可,取l=1,r=1e9;如果mid符合條件那麼我們就捨棄左邊部分,因爲是階乘,如果mid不符合條件,那麼1-mid也都是不符合,因此捨棄左邊部分,然後一直維護ans的值即可。

下面是AC代碼

#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e6+100;
int prime[maxn],num[maxn];
int k,t,p;
bool check(int x)
{
   
    for(int i=1;i<=k;i++)
    {
      int primernum=0,n=x;
      while(n)
      {
      primernum+=n/prime[i];
        n/=prime[i];
      }
      if(primernum<num[i])return false;
    }
    return true;
}
void solve()
{
    k=0;
  for(int i=2;i*i<=p;i++)
  {
      if(p%i==0)
      {
          prime[++k]=i;
          while(p%i==0)
          {
            num[k]++;
            p/=i;
          }
      }
  }
  if(p>1) prime[++k]=p,num[k]++;
  int l=1,r=1e9,mid,ans;
  while(l<=r)
  {
      mid=(l+r)/2;
      if(check(mid))r=mid-1,ans=mid;
      else l=mid+1;
  }
  memset(prime,0,sizeof prime);
  memset(num,0,sizeof num);
  cout<<ans<<endl;
}
int main()
{
   
    cin>>t;
    while(t--)
    {
      cin>>p;
      solve();
    }
    system("pause");
}

寫的很倉促,有錯誤請聯繫我。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章