在这道题上浪费了很长时间。
自己写的很不好。时间和空间均超出限制,虽然最后的结果是正确的。
下面是自己的代码。
#include<stdio.h>
#include<string.h>
char n[10001][36000];
int max;
void calculate(int i)
{
char temp[10];
memset(temp, 0, sizeof(temp));
int a = i, b = i + 1;
int c = 0;
while (b != 0)
{
temp[c++] = (b % 10) + '0';
b = b / 10;
}
b = i + 1;
int la = strlen(n[a]);
int lb = strlen(temp);
int p, q, r;
int bit = 0;
char mul[36000];
for (p = 0; p < lb; p++)
{
memset(mul, 0, sizeof(mul));
r = p;
bit = 0;
for (q = 0; q < la; q++)
{
mul[r++] = (bit + (n[a][q] - '0')*(temp[p] - '0')) % 10 + '0';
bit = ((n[a][q] - '0')*(temp[p] - '0') + bit) / 10;
}
int s1;
if (bit)
{
mul[r] = bit + '0';
s1 = r + 1;
}
else
s1 = r;
// add
int s2 = strlen(n[b]);
int s = s1 > s2 ? s1 : s2;
bit = 0;
for (q = 0; q < s; q++)
{
mul[q] = mul[q] == '\0' ? '0' : mul[q];
n[b][q] = n[b][q] == '\0' ? '0' : n[b][q];
int temp_bit = bit;
bit = ((n[b][q] - '0') + (mul[q] - '0') + bit) / 10;
n[b][q] = (((n[b][q] - '0') + (mul[q] - '0') + temp_bit) % 10) + '0';
}
if (bit)
n[b][q] = '1';
}
}
int main()
{
int m;
int i;
memset(n, 0, sizeof(n));
strncpy(n[0], "1", 1);
strncpy(n[1], "1", 1);
max = 1;
while (EOF != scanf("%d", &m))
{
if (max < m)
{
for (i = max; i <= m - 1; i++)
calculate(i);
max = m;
}
for (i = strlen(n[m]) - 1; i >= 0; i--)
{
if ('0' == n[m][i])
printf("0");
else
printf("%c", n[m][i]);
}
printf("\n");
}
return 0;
}
鼓励一下自己:实实在在的努力,没有水分的成功,总是震撼人心的风景。
此处小结。
我以前做大数有关的题目时,都是把一个大数作为一个字符串处理,大数的一位数字是字符串的一个字符。
现在学会了新的方法。
万进制。用一个int作为万进制的一位。当然千进制等依此类推。
读了题解后,得到下面的方法。最后改来改去,自己的代码几乎和题解一样。当作模板用吧。
首先是10进制。时间卡的很紧。MAX设为40000超时,36000就通过了。
#include <stdio.h>
#include <string.h>
#define BASE 10
#define MAX 36000
int r[MAX];
int main()
{
int n;
int i, j;
int bit;
while (EOF != scanf("%d", &n))
{
memset(r, 0, sizeof(r));
r[0] = 1;
for (i = 2; i <= n; i++)
{
bit = 0;
for (j = 0; j < MAX; j++)
{
r[j] = r[j] * i + bit;
bit = r[j] / BASE;
r[j] = r[j] % BASE;
}
}
for (i = MAX - 1; i >= 0; i--)
{
if (r[i])
break;
}
for (j = i; j >= 0; j--)
printf("%d", r[j]);
printf("\n");
}
return 0;
}
再尝试一下万进制。主要区别是BASE和MAX。
其中用到了printf("%04d"), 解释如下。
%nd 输出的整型宽度至少为n位,右对齐,%5d即宽度至少为5位,位数大于5则输出实际位数
%0nd 用得比较多,表示输出的整型宽度至少为n位,不足n位用0填充
printf("%05d",1)输出:00001
printf("%5d",1)输出:****1(*为空格)
附上代码。
#include <stdio.h>
#include <string.h>
#define BASE 10000
#define MAX 9000
int r[MAX];
int main()
{
int n;
int i, j;
int bit;
while (EOF != scanf("%d", &n))
{
memset(r, 0, sizeof(r));
r[0] = 1;
for (i = 2; i <= n; i++)
{
bit = 0;
for (j = 0; j < MAX; j++)
{
r[j] = r[j] * i + bit;
bit = r[j] / BASE;
r[j] = r[j] % BASE;
}
}
for (i = MAX - 1; i >= 0; i--)
{
if (r[i])
break;
}
for (j = i; j >= 0; j--)
{
if(j == i)
printf("%d", r[j]);
else
printf("%04d", r[j]);
}
printf("\n");
}
return 0;
}
时间大概是10进制的1/3到1/4。
先写到这里。
晚上回去的时候配置一下Java环境。尝试一下Java的大数类。
2018.6.24 更新
告别Eclipse,走向IntelliJ IDEA。
感觉pycharm,android studio,IntelliJ IDEA很像很像。
附代码。
运行的话要将类名改为Main。
import java.math.*;
import java.util.Scanner;
public class hduoj_1042 {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int i,n;
BigInteger r;
while(scanner.hasNext()){
n = scanner.nextInt();
r = new BigInteger("1");
if(0 == n)
{
System.out.println(r);
continue;
}
for(i=1;i<=n;i++)
r = r.multiply(new BigInteger(i + ""));
System.out.println(r);
}
}
}