_考查点:
数学思维。
_思路:
这个题用模拟的方法肯定会超时的,因为n!(n可以高达10^7),这个阶乘是一个非常大的数,
就算用高精度来存都很恐怖,最多能达到数量级上限千万位(n为10^7时有65657060位).
既然模拟不行.那么我们就想想数学方法吧。数学总是能带给我们惊喜。既然是求位数
那么就是就这个数以10为底的对数。哎,这么想就对了,既然是求对数那就简单了。
由对数的性质可以知道log10(n!) = log10(1) + log10(2) + ... + long10(n);这么就可以避免
数据太大造成的麻烦。但是直接这么写了提交还是会超时n能高达10^7...多来几次就TLE了。
那么我们可以事先求出间隔x增量的数的阶乘的对数存放在数组中。比如以一百万为间隔。
这样时间复杂度就降下来了。求一个case最多百万次循环.要更快,也可以以10万为间隔,但是那个
就要存100个数据,我太懒了,就选的100万为间隔的了。
_提交情况:
TLE一次,为事先打表。
_收获:
数学是个好东西啊!!!
_AC CODES:
#include <cstdio>
#include <cmath>
double array[11] = {0, 5565708.917187, 11733474.577126,
18128483.956099, 24671065.737818, 31323381.360738,
38063144.399049, 44875628.728418, 51750367.891344,
58679536.124036, 65657059.080059};
int main() {
int i, n, m;
scanf("%d", &n);
while (n--) {
scanf("%d", &m);
for (i = 10; i >= 0; i--) {
if (m >= i * 1000000) {
break;
}
}
double sum = array[i];
for (int j = i * 1000000 + 1; j<= m; j++) {
sum += log10((double)j);
}
int a = (int)sum;
if (1 == m || sum - a > 0) {//注意log10(1)是为0的.得单独讨论1 == m的情况
a++;
}
printf("%d\n", a);
}
return 0;
}