70,022
社区成员




#include<stdio.h>
#include<string.h>
#include<stdlib.h>
void reverse(char *s)
{
int len = strlen(s);
int i, j;
char c;
for (i = 0, j = len - 1; i < j; i++, j--)
{
c = *(s + i);
*(s + i) = *(s + j);
*(s + j) = c;
}
}
char *appendTailZero(char *s, int zeros)
{
int i, len = strlen(s);
char *r = malloc(len + zeros + 1);
for (i = 0; i < len; i++)
*(r + i) = *(s + i);
for (i = len; i < len + zeros; i++)
*(r + i) = '0';
*(r + len + zeros) = '\0';
return r;
}
char *add(char *s1, char *s2)
{
int l1 = strlen(s1);
int l2 = strlen(s2);
int len = l1 > l2 ? l1 : l2;
char *r = malloc(len + 2);
int i, prev = 0, a, b, sum;
for (i = 0; i < len; i++)
{
a = l1 - 1 - i >= 0 ? *(s1 + l1 - 1 - i) - '0' : 0;
b = l2 - 1 - i >= 0 ? *(s2 + l2 - 1 - i) - '0' : 0;
sum = a + b + prev;
*(r + i) = sum > 9 ? sum - 10 + '0' : sum + '0';
prev = sum > 9 ? 1 : 0;
}
if (prev)
{
*(r + len) = '1';
*(r + len + 1) = '\0';
}
else
*(r + len) = '\0';
reverse(r);
return r;
}
char *multiplyHelper(char *s1, int digit)
{
int i, res, prev = 0, len = strlen(s1);
char *r = malloc(len + 2);
if (!digit)
{
*r = '0';
*(r + 1) = '\0';
return r;
}
for (i = 0; i < len; i++)
{
res = (*(s1 + len - 1 - i) - '0') * digit + prev;
*(r + i) = res % 10 + '0';
prev = res / 10;
}
if (prev)
{
*(r + len) = prev + '0';
*(r + len + 1) = '\0';
}
else
*(r + len) = '\0';
reverse(r);
return r;
}
char *multiply(char *s1, char *s2)
{
if (strlen(s1) < strlen(s2))
{
char *temp;
temp = s1;
s1 = s2;
s2 = temp;
}
int l2 = strlen(s2);
int i;
char *t, *zt;
char *sum = malloc(2);
char *tp;
sum = "0";
for (i = 0; i < l2; i++)
{
tp = sum;
t = multiplyHelper(s1, *(s2 + l2 - 1 - i) - '0');
zt = appendTailZero(t, i);
sum = add(tp, zt);
free(t);
free(zt);
free(tp);//加入这行代码提交就报Runtime Error, 不加就Accepted,但是内存占用很大
}
return sum;
}
int main()
{
int k;
char m[5];
while (scanf("%d %s", &k, m) != EOF)
{
char *r = m;
int count = 1;
while (strlen(r) < k)
{
r = multiply(r, m);
count++;
}
r = r + strlen(r) - k;
while (*r != '7')
{
r = multiply(r, m);
r = r + strlen(r) - k;
count++;
}
printf("%d\n", count);
}
return 0;
}
/*
It was said that when testing the first computer designed by von Neumann, people gave the
following problem to both the legendary professor and the new computer: If the 4th digit
of 2^n is 7, what is the smallest n? The machine and von Neumann began computing at the
same moment, and von Neumann gave the answer first.
Now you are challenged with a similar but more complicated problem: If the K-th digit of
M^n is 7, what is the smallest n?
Input
Each case is given in a line with 2 numbers: K and M (< 1,000).
Output
For each test case, please output in a line the smallest n.
You can assume:
The answer always exist.
The answer is no more than 100.
Sample Input
3 2
4 2
4 3
Sample Output
15
21
11
*/
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int find_n(int k, int m);
int main()
{
int k,m;
while (scanf("%d %d", &k, &m) == 2)
printf("%d\n", find_n(m,k));
return 0;
}
/* test if the digit'th(starting from 0) digit of num's decimal representation is 7
* return 1 when test true, false otherwise.
*
* eg. test7(157434,2) is true, while test7(157432,3) is false
*
* note: num should be between 0 and 10^9-1
* and digit should be 0 to 8
*/
int test7(long num, int digit)
{
char _[10];
sprintf(_,"%ld", num);
return _[digit]=='7';
}
/* for debug only.
* I leave it behind because it sheds some light on how the large number
* should be interpreted
*
*/
void dump(long * p, int cnt)
{
printf("%d", p[cnt-1]);
for(int i=cnt-2; i>=0; --i)
printf("%09d",p[i]);
printf("\n");
}
void multiply(long* p, int* cnt_element, int m);
/* given integer k and m, find the smallest integer n such that
* the k'th digit of m^n (decimal representation) is 7
*
*/
int find_n(int k, int m)
{
// sizeof(long) is guaranteed to be 4
long array[34];
int cnt=1, // number of elements currently filled
n=1; // the value that we are looking for
array[0]=m; // we will put least significant int(s) in element 0
--k; // so that first digit is the 0th digit
while( cnt< k/9 || !test7(array[k/9], k%9) )
{
++n;
multiply(array, &cnt, m);
}
return n;
}
/* our ad hoc large number multiplication function
* param: p: points to array of long's which represent a large number. note the least
* significant element is the 0th element and each element should be between
* 0 and 10^9-1;
* pcnt: points to number of elements actually used in the above array
* m: number to multiply into the large number(no more than 100 according to problem description)
*
*
*/
void multiply(long* p, int* pcnt, int m)
{
long long v=0;
long carry=0;
for(int i=0; i<*pcnt; ++i)
{
v=carry+(long long)p[i]*m;
p[i]=(long)(v%1000000000);
carry=(long)(v/1000000000);
}
if(carry)
p[(*pcnt)++]=carry;
}
while (strlen(r) < k)
{
r = multiply(r, m);
count++;
}
第一遍的时候r就是m, 等于计算m的平方,这个确实不需要free, 第二遍的时候那个r已经是动态分配的了,你如果不free掉它就直接把multiply的运算结果(一个新的动态分配的内存指针)赋给r, 那么前一次分配的内存就泄露了,如此反复,除了最后一个有用,之前的都泄露了......
int main()
{
int k;
char m[5];
while (scanf("%d %s", &k, m) != EOF)
{
char *r = m;
int count = 1;
while (strlen(r) < k)
{
char * tmp=multiply(r, m);
if(r!=m)
free(r);
r = tmp;
count++;
}
r += strlen(r) - k;
while (*r != '7')
{
char *tmp=multiply(r, m);
if(r!=m) // you should be able to skip this line!!
free(r);
r=tmp;
r += strlen(r) - k;
count++;
}
printf("%d\n", count);
}
return 0;
}
对应的, main应该做如上修改。没有查你的程序的逻辑和其他问题,不保证能通过。
char *sum = malloc(2);
char *tp;
sum = "0";
for (i = 0; i < l2; i++)
{
tp = sum;
t = multiplyHelper(s1, *(s2 + l2 - 1 - i) - '0');
zt = appendTailZero(t, i);
sum = add(tp, zt);
free(t);
free(zt);
}
return sum;
}
tp就是sum, 循环体第二次再进入时那个指针就已经free掉了, tp和sum都指向未定义的内存位置了。不可以在循环体内free. 又因为你把返回值放在那里,如果你在本函数结束前free掉tp(亦即sum),调用函数使用返回值的时候又会发生访问错误,所以应该由调用者free.