题意:找到满足x!的尾部有m个0的所有正整数x
被cmath里的pow函数坑了,,,不明白为什么。。。
找到了那个WA的test,我的VS2013运行就没问题,但是在评测机上就有问题。。。
官方的思路是二分,不过我的不是,,,有时间再贴讲解吧,,感觉我的思路也没什么意思
嗯,先来写写官方的思路,用二分,找到最小的尾部有m个0的数x,然后依次++,一直到尾部的0多于m。
然后,我的思路,,就有点奇葩。
我是先列举5,25,125,625,…他们的阶乘尾部各有多少个0。0的话,是由10组成的,即2*5,只要有5,2是充分足够的5用的。
5的尾部肯定是1个,25的话,5,10,15,20,各会提供一个10,但是25的话,会提供两个0,因为他有两个5,所以一共是6个。
同理,50也会提供2个0,75,100,都是,提供两个0。
125,125会提供三个0,所有是25的倍数的,都会提供两个0,是5的倍数但不是25的倍数的会提供1个0。
也就是说,所有5的倍数的会提供1个0,即一共25个,所有25的倍数的会再提供一个0,即又来5个,然后所有125的倍数的会再提供一个0,又来一个,就是1+5+25=31个。
所以,对于5^i,它的阶乘的尾部的0的个数是,1+5+25+…+5^(i-1)=(5^i-1)/4,好吧,我代码里写的是5^i /4,不过是整除,也不影响结果,但是还是应该改掉。
然后求出来之后,比如要找70个0的,125的阶乘会提供31个0,625提供的0大于70,所以不会超过625。70/31=2,70%31=8,125!可以提供31个0,同样,250*249*...*126,也可以提供31个0。道理都是一样的,只不过125!里出现的是5,10,15,,,,25,50,,75,,100,,125。250!/125!里出现的是130,,135,,140,,150,,175,,200,,,225,,,250,,提供的0都是一样的。所以是250!会提供62个0,然后还剩8个0,25!会提供6个0,然后再加个25,就是275,然后还剩两个0,10!会提供两个0,所以再加个10,就是285。这个讲的就是我的work函数。当然还有无法组成的情况,比如恰有5个0的,5的阶乘会提供1个0,就是5*5,但是5*5,的后面这个系数5,会再提供一个0,所以,假如除了之后的商是5,那就是无法组成的。。。
唉,,,本来很简单一个二分+暴力找的题,活生生被我搞得这么复杂。。智商捉急。。
再来看看怎么求一个数的阶乘的尾部有多少个0。
inline int get(int n) { int z = 0; while (n > 0) { n /= 5; z += n; } return z; }
这是t神的代码,跟我上面求5^i的尾部有多少个0的公式其实是一样的,而且因为这里的/是整除,所以即使n不是5的倍数,也没关系。。。然后这个东西再配一个二分就是官方的解答了
这里是我的代码:
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <string> #include <algorithm> #include <map> using namespace std; int five_pow[10]; int zero_num[100000]; int ans = 0; int powi(int a, int b) { int ans = 1; for (int i = 0; i < b; ++i) ans *= a; return ans; } bool work(int m, int i) { if (m == 0) return true; int t = powi(5, i); if (m >= five_pow[i]) { int n = m%five_pow[i]; int t1 = m / five_pow[i]; if (t1 >= 5) return false; ans += t1 * t; m = n; } return work(m, i - 1); } int main() { int m; scanf("%d", &m); for (int i = 1; i < 10; ++i) five_pow[i] = (powi(5, i) - 1) / 4; if (work(m, 8)) { printf("5\n"); for (int i = 0; i < 5; ++i) { if (i > 0) printf(" "); printf("%d", ans + i); } } else printf("0"); printf("\n"); //printf("ans %d\n", ans); //while (1); return 0; }