Wannafly挑戰賽25A——質因子分解
阿新 • • 發佈:2018-12-12
題目總結:哇,還真是質因子篩選!考試的時候想到了質因子個數相除,但不知道一個階乘該如何計算出一個因子的個數......
求一個大數n的階乘的所含因子p的個數,我們知道,
n!=1*2*3*4*......n
為求出p的個數,將上式表示為
n!=(p*2p*3p*4p*......*kp)*q,其中q就是其他不是因子p的倍數的乘積,比如10!=(2*(2*2)*(3*2)*......(5*2))*q,q是不含p的可以不管,k=n/p;
這樣,我們可以提出k個p出來,原式為
n!=p^k*k!*q,再將k!像上面的方法一樣分解,就可以得到p的個數
程式碼如下:
//階乘因子分解,找出n!中有多少個p ll findnum(ll n,ll p) { ll ans=0;//個數 if(k==0)return 0; while(n) { ans+=n/p;//一次變換後的個數 n/=p;//將k=n/p再迭代 } return ans; }
那麼,我們就可以將給定的p進行質因子分解,找出質因子和它們的個數,再用上述方法找到n!中p的每個質因子的個數,找到兩者相除的最小值就是答案。
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cmath> using namespace std; typedef long long ll; /* 篩出p的最小質數和個數,再用快速演算法求出n!中含有多少個最小質數 兩者個數相處就得到答案k 快速求N!中有多少質數m的演算法就是迭代公式 */ const ll maxn=10001; int isprime[maxn]; int notprime[maxn]; ll n_num[maxn];//n的每個質因子個數 ll p_num[maxn];//p的每個質因子個數 int cnt; //篩選質數 void eular() { memset(isprime,0,sizeof(isprime)); memset(notprime,0,sizeof(notprime)); cnt=0; for(int i=2;i<maxn;i++) { if(!notprime[i]) { isprime[++cnt]=i; } for(int j=1;j<=cnt&&i*isprime[j]<maxn;j++) { notprime[i*isprime[j]]=1; if(i%isprime[j]==0) break; } } } //階乘因子分解,找出n!中有多少個p ll findnum(ll n,ll p) { ll ans=0; while(n) { ans+=n/p; n/=p; } return ans; } int main() { ll n,p; eular(); int tot=1; while(scanf("%lld%lld",&n,&p)!=EOF) { memset(n_num,0,sizeof(n_num)); memset(p_num,0,sizeof(p_num)); while(p!=1) { //求p的每個質因子的個數 while(p%isprime[tot]==0&&p) { p_num[tot]++; p/=isprime[tot]; } tot++; } for(int i=1;i<=tot;i++) { n_num[i]=findnum(n,isprime[i]); } ll ans=2e18+5; for(int i=1;i<=cnt;i++) { if(p_num[i]) ans=min(ans,n_num[i]/p_num[i]);//找一個最小的因子數之商 } printf("%lld\n",ans); } return 0; }