階乘末尾0的個數(二分+數論)
阿新 • • 發佈:2020-11-02
設計一個演算法,計算出n階乘中尾部零的個數 樣例 11! = 39916800,因此應該返回 2 挑戰 O(logN)的時間複雜度
要判斷末尾有幾個0就是判斷可以整除幾次10。10的因子有5和2,而在0~9之間5的倍數只有一個,2的倍數相對較多,所以本題也就轉換成了求N階乘中有幾個5的倍數。比如10的階乘,10之內有2個5的倍數,10/5=2,2之內則沒有了可以匹配的5了,所以一共2個5。
還有25階乘中貢獻了6(25/5+5/5)個5,因為有5的倍數的倍數(25=5*5,貢獻2個5),所以就有了count += n/5,在先求一批5的個數後,再求第二批5的個數。
同理 125中 5的個數等於125/5 + 25/5 +5/5=31;
#include<iostream> using namespace std; int main() { int n; cin>>n; int count = 0; while(n) { n /= 5; //算出當前數字中可以匹配5(5和5的倍數)的個數 count += n; //累加之 } cout<<count; return 0; }
n的階乘尾部有q個連續的0,現在給你q,請你算出滿足條件的n,如果有多個n滿足條件,輸出最小的那個即可。
Input
輸入一個T(T <= 10000),表示樣例數量。
每個樣例輸入一個q。(1 <= q <= 100,000,000)
Output
對於每個樣例,輸出滿足條件的最小的n,如果沒有滿足條件的則輸出"impossible"。.
Sample Input
3
1
2
5
Sample Output
Case 1: 5
Case 2: 10
Case 3: impossible
解析:因為階乘中0的個數是按照數的增大而遞增的(滿足單調性)
#include<iostream> #include<algorithm> using namespace std; //因為0的個數是隨這數的增加而增加的int judge(int x){ int ans=0; while(x){ ans+=x/5; x/=5; } return ans; } int main(){ int t,n; cin>>t; int kase=0; while(t--){ cin>>n; int l=0,r=1e9; int ans=0; while(l<=r){ int mid=(l+r)/2; int p=judge(mid); if(p>=n){ r=mid-1; ans=mid; } else{ l=mid+1; } } ans=(ans-ans%5);//因為是最小的那個 if(judge(ans)==n) printf("Case %d: %d\n",++kase,ans); else{ printf("Case %d: impossible\n",++kase); } } }