题目
Origin | Title | Satus |
---|---|---|
UVA 424 | Integer Inquiry | AC |
UVA 10106 | Product | AC |
UVA 465 | Overflow | AC |
UVA 748 | Exponentiation | AC |
UVA 10494 | If We Were a Child Again | AC |
UVA 424 Integer Inquiry
分析
大数相加可以通过模拟来实现,即两大数从个位起逐位数字相加,相加得到的数字范围在[0, 18]之间,再与结果集当前位相加(此时范围应在[0,19]之间),取十位置入结果集的进一位,取个位置入结果集的本位.
1 2
+ 8 9
—————-
(0)11
1
(1)9
0
(1)
1
—————-
1 0 1由上述可知,将大数倒序存储是一个好的选择.
- 此外,为了方便地输入,较多使用字符数组存储,在做数字运算时,切勿忘记
-‘0’
以获得数字. - 还有一件事,高精度运算类的题目在调试时,可以尝试输出中间量,以检查算法是否正确.
- 还有一件事,因为是倒序存储,那么前导0是必须处理的,可以从结果集的最高位向下减小直到当前位不是0,也可以设置一个最高位索引(注意进位时索引也要增加). 从此位倒序输出倒序数组,即获得无前导0的正序大数.
代码
#include <stdio.h>
#include <string.h>
int main(void)
{
char cn[120];
int in[120], i, j, k;
memset(in, 0, sizeof(in));
while (fgets(cn, 120, stdin) && cn[0] != '0') {
for (i = strlen(cn)-2, j = 0; i >= 0; i--, j++) {
in[j] = in[j] + (cn[i] - '0');
k = j;
while (in[k++] > 9) {
in[k] += in[k-1]/10;
in[k-1] %= 10;
}
}
}
for (i = 120-1; in[i] == 0; i--);
for (; i >= 0; i--)
printf("%d", in[i]);
printf("\n");
return 0;
}
UVA 10106 Product
分析
大数乘法,可以模拟.
1 2
× 1 2
—————-
(0)4
4
(0)2
2
(2)2
4
(0)1
1
—————-
1 4 4建议将较大的数组放入全局区,避免RE(
Runtime error
)嗯.
代码
#include <stdio.h>
#include <string.h>
int main(void)
{
char a[300], b[300];
int r[90000], x[300], y[300];
int i, j, k;
while (fgets(a, 300, stdin), fgets(b, 300, stdin)) {
memset(x, 0, sizeof(x));
memset(y, 0, sizeof(y));
memset(r, 0, sizeof(r));
for (i = strlen(a)-2, j = 0; i >= 0; i--, j++) x[j] = a[i] - '0';
for (i = strlen(b)-2, j = 0; i >= 0; i--, j++) y[j] = b[i] - '0';
for (i = 0; i < strlen(a)-1; i++)
for (j = 0; j < strlen(b)-1; j++) {
r[i+j] += x[i] * y[j];
if (r[i+j] > 9) {
r[i+j+1] += r[i+j]/10;
r[i+j] = r[i+j]%10;
}
}
for (k = i * j; r[k] == 0 && k > 0; k--);
for (; k >= 0; k--) printf("%d", r[k]); printf("\n");
}
return 0;
}
UVA 465 Overflow
分析
- int有点小,会溢出,换double问题解决(并不是适用于所有情况,比如可能会影响到精度问题)~
- 关于int的范围可以参见
<limits.h>
.
/* Minimum and maximum values a `signed int’ can hold. */
# define INT_MIN (-INT_MAX - 1)
# define INT_MAX 2147483647
代码
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char fs[600], ss[600], op;
double f, s, r;
while (scanf("%s %c %s", fs, &op, ss) != EOF) {
printf("%s %c %s\n", fs, op, ss);
f = atof(fs);
s = atof(ss);
if (op == '*') r = f * s;
if (op == '+') r = f + s;
/* 2^31 - 1 */
if (f > 2147483647) printf("first number too big\n");
if (s > 2147483647) printf("second number too big\n");
if (r > 2147483647) printf("result too big\n");
}
return 0;
}
UVA 748 Exponentiation
分析
- 求k次幂,可以把它当作k次乘法,一个数的第i(i = 0, 1, 2, … , k-1)次幂与其本身相乘.
- 本题的数据带有小数点,但是小数点可以在计算时忽略,为什么呢?因为小数点的移动步长是可以推算的,无需在计算时带入.
- 注意前导0和后导0.
代码
#include <stdio.h>
#include <string.h>
int res[310], num[6], numc[310];
void cal_exp(int n)
{
int i, j;
/* base */
if (n == 1)
return;
for (i = 0; i < 5; i++) {
for (j = 0; j < 300; j++) {
numc[i+j] += num[i] * res[j];
if (numc[i+j] > 9) {
numc[i+j+1] += numc[i+j]/10;
numc[i+j] = numc[i+j]%10;
}
}
}
for (i = 0; i < 310; i++) {
res[i] = numc[i];
numc[i] = 0;
}
cal_exp(n-1);
}
int main(void)
{
char tmp[6], r[310];
int i, j, k, n, pos;
while (scanf("%s%d", tmp, &n) == 2) {
memset(num, 0, sizeof(num));
memset(res, 0, sizeof(res));
for (i = 5, j = 0; i >= 0; i--) {
if (tmp[i] != '.') {
res[j] = tmp[i] - '0';
num[j++] = tmp[i] - '0';
} else {
pos = 5-i;
}
}
memset(numc, 0, sizeof(numc));
memset(r, '\0', sizeof(r));
cal_exp(n);
for (k = 0, i = 0; res[i]==0; i++, k++);
for (j = 0; i < 310; i++) {
if (k == n * pos) r[j++] = '.';
r[j++] = res[i] + '0';
k++;
}
for (i = 310-1; r[i] == 0 || r[i] == 48; i--);
for (; i >=0; i--)
printf("%c", r[i]);
printf("\n");
}
return 0;
}
UVA 10494 If We Were a Child Again
分析
小数除大数,大数除以小数,模拟走起,被除数从最高位起,向下一位取数,再除以除数,得到的即是商,最后被除数位数排满了,即再做除法运算将获得小数的数即为余数.
_________
12 ) 1 4 5
(0)1 / 12 = 0 …… (1)
(1)4 / 12 = 1 …… (2)
(2)5 / 12 = 2 …… [1]_0__1__2_ …… 1
12 ) 1 4 5重要的事情记三遍: 0!
代码
#include <stdio.h>
#include <string.h>
#define MAXN 1005
char a[MAXN], c, div[MAXN];
long b, mod;
void cal(void)
{
int i;
long long n = 0;
for (i = 0; i < strlen(a); i++) {
n = n*10 + (a[i] - '0');
div[i] = (n / b) + '0';
n = n % b;
}
mod = n;
return;
}
int main(void)
{
int i;
while (scanf("%s", a) == 1) {
while ((c = getchar()) == ' ');
scanf("%lld", &b);
memset(div, '\0', sizeof(div));
cal();
if (c == '/') {
for (i = 0; div[i]=='0' && i < strlen(div)-1; i++);
for (; i < strlen(div); i++)
printf("%c", div[i]);
printf("\n");
} else if (c == '%') {
printf("%lld\n", mod);
}
}
return 0;
}