版权声明:感谢查看,转载请注明原地址,知识与您同在。 https://blog.csdn.net/a1023182899/article/details/84874493
题目描述
三角数:圆点摆放成等边三角形的数字,则为三角数。1,3,6,10,15,21,28,36…
平方数:小方块摆放成正方形的数字,则为平方数。1,4,9,16,25,36…
那么如果一个数字既是三角形数又是平方数,则称为三角平方数。很显然我们知道第一个三角平方数就是1了。
那么第n个三角平方数是哪个呢?
输入
输入一个正整数n (1≤n≤200)
输出
输出第n个三角平方数
借用ismdeep的回答通过打表,或者直接百度三角平方数,列出前面一些数据
1, 36, 1225, 41616, 1413721, 48024900, 1631432881, 55420693056, 1882672131025, 63955431761796, 2172602007770041, 73804512832419600, 2507180834294496361, 85170343853180456676, 2893284510173841030625
然后在oeis上搜索。http://oeis.org/A001110,得到递推公式
a(0) = 0, a(1) = 1; for n >= 2, a(n) = 34 * a(n-1) - a(n-2) + 2.
他的码云https://gitee.com/ismdeep**
#include<stdio.h>
#include<string.h>
#define MAX 1000 // 大数的最大位数
char z_all[MAX]; //存放乘法结果
char reduce[MAX];
char plus[MAX];
char *multi_bignum(char x[MAX], char y[MAX])
{
//char x[MAX];
//char y[MAX];
//char z_all[MAX];
memset(z_all, 0,MAX* sizeof(char));//不能变成strcpy(z_all,"0");
//printf("z_all[3]%c\n", z_all[3]);
char z[MAX];//存放每次乘法结果
char big[MAX];//存放x[]和y[]更大的那个数组 ,相当于列式计算的上面那个数
char small[MAX];//存放x[]和y[]更小的那个数组 ,相当于列式计算的下面那个数
int multi = 0;//2个数相乘得到的
int count = 0;//乘法进位的数
int length = 0;//用于计算z[]的长度
int length_all = 0; //用于计算z_all[]的长度,很难搞,因为ascii0代表为\0,所以strlen(z_all)没用,length_all=length或者length+1或-1
int plus = 0;//2个数相加得到的
int count_z = 0;//加法进位的数
//scanf("%s",&x);
//scanf("%s",&y);
int x_length = strlen(x);
int big_length = 0;//记录x_length和y_length更大的长度为
int y_length = strlen(y);
int small_length = 0;//记录x_length和y_length更小的长度为
//1,判断x[]和y[]谁更长,得到长度,并把更长的放入big[],更短的放入small[]
//2,每一位都-48,才可以开始计算。
if (x_length > y_length)
{
big_length = x_length;
small_length = y_length;
for (int i = 0; i < (big_length); i++)
{
big[i] = x[i] - 48;
if (i < y_length)
small[i] = y[i] - 48;
else small[i] = 0;
}
}
else
{
big_length = y_length;
small_length = x_length;
for (int i = 0; i < (big_length); i++)
{
big[i] = y[i] - 48;
if (i < x_length)
small[i] = x[i] - 48;
else small[i] = 0;
}
}
//字符串逆转strrev(),不能用这个函数,和strlen()一样,碰ascii0结束
//strrev(big);
int num = big_length / 2;
int first_num = 0;//执行字符串逆转的
for (int i = 0; i < num; i++)
{
first_num = big[i];
big[i] = big[big_length - 1 - i];
big[big_length - 1 - i] = first_num;
}
//strrev(small);
num = small_length / 2;
for (int i = 0; i < num; i++)
{
first_num = small[i];
small[i] = small[small_length - 1 - i];
small[small_length - 1 - i] = first_num;
}
//--------------------计算每次结果,并执行加法,得到总结果
for (int i = 0; i < small_length; i++)
{
memset(z, 0, sizeof(z));//用完数组一定要记得情空
count = 0;
length = 0;
for (int j = 0; j < big_length; j++)
{
multi = small[i] * big[j] + count;
if (multi < 10)
{
count = 0;
}
else count = multi / 10;
z[j] = multi % 10;
length++;
//每次运算结果的第一位可能需要进位
if (j == big_length - 1)
{
if (multi >= 10)
{
length++;
z[j + 1] = multi / 10;
}
count = 0; //运算完了之后进位为0
}
}
//逆转每次运算结果再加上根据正在计算small[]中第几个数决定末尾的0,真正的每次运算结果
//strrev(z);//字符串逆转
num = length / 2;
for (int m = 0; m < num; m++)
{
first_num = z[m];
z[m] = z[length - 1 - m];
z[length - 1 - m] = first_num;
}
//根据正在计算small[]中第几个数决定末尾的0,真正的每次运算结果
for (int m = 0; m < i; m++)
{
z[length] = 0;
length++;
}
//在每次 执行z_all[]和z[] 的加法 之前先对z_all[]补充到和z[]一样的位数
//可能补充1位,可能补充2位
if (length_all == length)
;
else
{
//1 是 -1,2是+0,3是+1 ,4是 +2,相差2
//观察得到 length-length_all-2 是
for (int m = length + (length - length_all - 2); m >= length - length_all; m--)
{
z_all[m] = z_all[m - (length - length_all)];
}
for (int m = 0; m < length - length_all; m++)
{
z_all[m] = 0;
}
length_all = length;
}
//加起来存放在z_all[],执行z_all[]和z[] 的加法
for (int m = (length - 1); m >= 0; m--)
{
plus = z[m] + z_all[m] + count_z;
if (plus >= 10)
{
count_z = 1;
z_all[m] = plus % 10;
//每次运算结果的第一位可能需要进位
if (m == 0)
{
count_z = 0;
//必须这样写,不然strlen()以\0结束,而ascii的0就是\0
length_all = length + 1;
for (int n = length; n > 0; n--)
{
z_all[n] = z_all[n - 1];
}
z_all[0] = 1;
}
}
else
{
z_all[m] = plus;
count_z = 0;
}
}
}
//--------------------得到总结果
//还原成char[],才可以用字符串%s显示出来,不然可能要一个一个%d输出
for (int i = 0; i < length_all; i++)
{
z_all[i] += 48;
}
//printf("总结果为%s",z_all);
//函数不要返回局部变量的指针,因为这是不确定的行为,指针所指的内容函数结束后就自动释放了,之后的值可能被其他内容覆盖
return z_all;
}
char *Subtraction(char num1[], char num2[])
{
int sum[MAX] = { 0 }; // 存放计算的结果
memset(sum, 0, sizeof(int)*MAX);
//char reduce[MAX];
memset(reduce, 0, MAX * sizeof(char));
int i, j, len, blag;
char *temp;
int n2[MAX] = { 0 };
int len1 = strlen(num1); // 计算数组num1的长度,即大数的位数
int len2 = strlen(num2); // 计算数组num2的长度,即大数的位数
// 在进行减法之前要进行一些预处理
blag = 0; // 为0表示结果是正整数,为1表示结果是负整数
if (len1 < len2) // 如果被减数位数小于减数
{
blag = 1; // 标记结果为负数
// 交换两个数,便于计算
temp = num1;
num1 = num2;
num2 = temp;
len = len1;
len1 = len2;
len2 = len;
}
else if (len1 == len2) // 如果被减数的位数等于减数的位数
{
// 判断哪个数大
for (i = 0; i < len1; i++)
{
if (num1[i] == num2[i])
continue;
if (num1[i] > num2[i])
{
blag = 0; // 标记结果为正数
break;
}
else
{
blag = 1; // 标记结果为负数
// 交换两个数,便于计算
temp = num1;
num1 = num2;
num2 = temp;
break;
}
}
}
len = len1 > len2 ? len1 : len2; // 获取较大的位数
//将num1字符数组的数字转换为整型数且逆向保存在整型数组sum中,即低位在前,高位在后
for (i = len1 - 1, j = 0; i >= 0; i--, j++)
sum[j] = num1[i] - '0';
// 转换第二个数
for (i = len2 - 1, j = 0; i >= 0; i--, j++)
n2[j] = num2[i] - '0';
// 将两个大数相减
for (i = 0; i <= len; i++)
{
sum[i] = sum[i] - n2[i]; // 两个数从低位开始相减
if (sum[i] < 0) // 判断是否有借位
{ // 借位
sum[i] += 10;
sum[i + 1]--;
}
}
// 计算结果长度
for (i = len1 - 1; i >= 0 && sum[i] == 0; i--)
;
len = i + 1;
if (blag == 1)
{
sum[len] = -1; // 在高位添加一个-1表示负数
len++;
}
if (sum[i = len - 1] < 0) // 根据高位是否是-1判断是否是负数
{
//printf("-"); // 输出负号
i--;
}
int jj = 0;
for (; i >= 0; i--)
{
reduce[jj++] = sum[i] + 48;
}
return reduce; // 返回结果的位数
}
char *Addition(char num1[], char num2[])
{
int sum[MAX] = { 0 }; // 存放计算的结果
memset(sum, 0, sizeof(int)*MAX);
//char plus[MAX];
memset(plus, 0, MAX * sizeof(char));
int i, j, len;
int n2[MAX] = { 0 };
int len1 = strlen(num1); // 计算数组num1的长度,即大数的位数
int len2 = strlen(num2); // 计算数组num2的长度,即大数的位数
int count1 = 0;
int count2 = 0;
for (int i = 0; i < len1; i++)
{
if (num1[i] == '0')
count1++;
}
for (int i = 0; i < len2; i++)
{
if (num2[i] == '0')
count2++;
}
if (count1 == len1 && count2 == len2)
{
strcpy(plus, "0");
return plus;
}
else if (count1 == len1)
{
strcpy(plus, num2);
return plus;
}
else if (count2 == len2)
{
strcpy(plus, num1);
return plus;
}
len = len1 > len2 ? len1 : len2; // 获取较大的位数
//将num1字符数组的数字字符转换为整型数字,且逆向保存在整型数组sum中,即低位在前,高位在后
for (i = len1 - 1, j = 0; i >= 0; i--, j++)
sum[j] = num1[i] - '0';
// 转换第二个数
for (i = len2 - 1, j = 0; i >= 0; i--, j++)
n2[j] = num2[i] - '0';
// 将两个大数相加
for (i = 0; i <= len; i++)
{
sum[i] += n2[i]; // 两个数从低位开始相加
if (sum[i] > 9) // 判断是否有进位
{ // 进位
sum[i] -= 10;
sum[i + 1]++;
}
}
if (sum[len] != 0) // 判断最高位是否有进位
len++;
int jj = 0;
for (i = len - 1; i >= 0; i--)
plus[jj++] = sum[i] + 48;
char plus_last[MAX];
memset(plus_last, 0, MAX * sizeof(char));
if (plus[0] != '0')
return plus;
else
{
int l = strlen(plus);
for (int i = 0; i < l; i++)
{
if (plus[i] != '0')
{
int flag = 0;
for (; i < l; i++)
{
plus_last[flag++] = plus[i];
}
strcpy(plus, plus_last);
return plus;
}
}
}
return plus;
}
int main()
{
char a[MAX][MAX];
strcpy(a[0], "0");
strcpy(a[1], "1");
char thirty_four[3] = "34";
char two[2]= "2";
int n;
scanf("%d", &n);
for (int i = 2; i <= n; i++)
{
multi_bignum(thirty_four, a[i - 1]);
Subtraction(z_all, a[i - 2]);
strcpy(a[i], Addition(reduce, two));
}
printf("%s\n", a[n]);
return 0;
}
我的答案和正确答案一模一样,从1-200输出结果放到txt,md5也一样,就是WA
发现是返回了局部变量的指针,OJ应该提示runtime error的