Trailing Zeroes (III) LightOJ - 1138

原题链接

考察:思维+二分

错误思路:

       根据分析可以发现当n为5的倍数时,n!会多>=1个0.如果n能分解k个5.那么会在(n-5)!的基础上多k个0.看到这里可能会想到前缀和预处理,但是当n=1e8时,它的0还未到1e8个.如果用数组存储会MLE.

正确思路:

       不能预处理只能每个每个地算,但是每次都每5个找一个是不现实的.可以发现n越大阶乘的0越多,也就是说这种性质有显然的单调性.因此用二分处理.那么如何找1~n的所有能分解出5的个数呢?联想到阶乘分解那道题.5的倍数有n/5个,贡献2个5的有n/25个.与上道题的阶乘分解的思想相同.可以让n/=5或t*=5求解能够分解多个5的数的贡献

注意:

       n/25是不需要*5的,因为n/5已经算了一次

虽然代码写的是t*=5,但是用n/=5更好

 

 1 #include <iostream>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 typedef long long ll;
 6 ll check(ll n)
 7 {
 8     int ans = 0;ll t = 5;
 9     while(n/t!=0)
10     {
11         ans+=n/t;
12         t*=5ll;//k次5看是否有 5^k的倍数 因为5的倍数在每次除的时候都去掉了一个5的因子 
13     }
14     return ans;
15 }
16 int main()
17 {
18     int T,kcase = 0,m;
19     scanf("%d",&T);
20     while(T--)
21     {
22         scanf("%d",&m);
23         ll low = 5,high = 1e9;
24         while(low<high)
25         {
26             ll mid = (low+high)/2;
27             if(check(mid)>=m) high = mid;
28             else low = mid+1;
29         }
30         if(check(low)==m) printf("Case %d: %lld\n",++kcase,low);
31         else printf("Case %d: impossible\n",++kcase);
32     }
33     return 0;
34 } 

 

posted @ 2021-01-27 14:02  acmloser  阅读(43)  评论(0编辑  收藏  举报