大数相乘。。。。

1.自守数

一个数的平方的尾数等于这个数的数是自守数
法一

//知识点:若要分离一个数的最后x位,只需要用次数对10^x取余即可,注意这里的最后x位指的是它表示的实际数值,不是仅仅一个数,例如我想求345的最后2位数,我用345 % 100得到的是45,而不是4,想要得到4需要这么做345 % 100 - 345 % (100 / 10), 这就是自守数算法中的重要步骤,当然取4也可以用(345 % 100) / 10得到,这种方法我用在求水仙花数的一类题上

#include<stdio.h>
int main()
{
	int mul, number, k, b, c;
	printf("1-10000之间共有这些自守数:\n");
	for (number = 1; number < 10000; number++)
	{		for (mul = number, k = 10; (mul /= 10) > 0; k *= 10);
			//k控制着求部分积的次数,k的n次方代表求n次部分积,每次以10倍递减,例如number为25,得出k为100,求两次部分积
			c = k;//每次对每次部分积截取后几位,例如c为100(10^2),证明每次截取后两位
		mul = 0;//用来累加结果
		b = 10;//因为第一次截取乘数肯定截取的是它的最后一位,由知识点可知b初始值为10
		while (k > 1)//控制着次数
		{
			mul = (mul + (number%k)*(number%b - number % (b / 10)) )% c;//难点,也是核心语句
			k = k / 10;
			b = b * 10;
		}
		if (mul == number)
		{
			printf("%d\n", mul);
		}
	}
	return 0;
}
/*思路过程:
		1.要求1 - 10000中所有的自守数,肯定少不了对每个数遍历判断的操作(最外层for循环)
		2.拿到一个数下一步该怎么做呢,就用到了图片中的算法思想,从中理解出,对于每次求得的部分积,我都要取它的最后"位数"位数,比如number位25,则我每次部分积要取它的最后2位,如何求最后两位呢?请看知识点中的讲解,所以第二步我们就要通过number的位数确定这个"10的乘方数",比如number为5,自然k取10.
		3.开始进行while循环中的操作了,对mul = (mul + (number%k)*(number%b - number % (b / 10)) % c; 进行如下讲解:
			将这一长串分为两部分看,第一部分(number%k)。第二部分(number%b - number % (b / 10)。再看看图片中的算法思想和知识点中的讲解就恍然大悟了,后面的对c取余,也是算法思想中说的,对各个部分积后三位求和后,再对最终结果后三位求和。
------------------------------------------------------------------------------------------
下面代码是我之前自己写的求自守数的方法,显然跟上面比相差太多了*/
#include<stdio.h>
int main()
	{
		int a[10], i, j, k = 0, sum, n = 0, m = 0, p, q, s;
		for (i = 1; i < 10000; i++)
		{
			p = 1;//用于将数组尾数变成一个数时用的变量
			k = 0;//记录某个数的平方是几位数
			j = i * i;
			m = 0;
			s = i;
			q = 0;
			sum = 0;
			while (s % 10 != 0)//用q保存所求数是几位数
			{
				q++;
				s = s / 10;
			}
			while (j % 10 != 0)//k保存所求数的平方是几位数,并将其逆序保存在数组中
			{
				a[k] = j % 10;
				k++;
				j = j / 10;
			}
			while (m < q)//算出平方数的最后几位,由于是逆序存储则可以直接计算
			{
				sum = sum + p * a[m];
				p = p * 10;
				m++;
			}
			if (sum == i)
			{
				printf("%d\n", sum);
			}

		}
	}

2.两个极大数相乘

错误示范

#include<stdio.h>
int main()
{
	//char str[100];//存结果
	int a, b;
	scanf("%d %d", &a, &b);
	char *MMax(int, int);
	printf("%s\n", MMax(a, b));
	return 0;
	
}
char s[20] = { 0 };
char *MMax(int a, int b)
{
	int sum = 0, temp1 = 0, m,k=0;
	char *p = s;
	int  i = 0;
	if (a > b)
	{
		int temp;
		temp = a;
		a = b;
		b = temp;
	}
	while (b)
	{
		s[i++] = b % 10+'0';
		b /= 10;
	}
	for (m = 0; m < i; m++)
	{
		sum = (s[m]-'0') * a + temp1;
		s[k++] = (sum % 10)+'0';
		temp1 = sum / 10;
	}
	if (temp1)
	{
		s[m++] = (temp1%10)+'0';
		temp1 /= 10;
	}
	s[m] = '\0';
	return p;
}
/*
妄图返回指向结果数组的字符指针,却殊不知,s数组的生命周期出了MMax函数就结束了,所以此时的p也是没有指向的,所以结果出错

*/

正确

#include<stdio.h>
int main()
{
	//char str[100];//存结果
	int a, b;
	scanf("%d %d", &a, &b);
	void MMax(int, int);
	MMax(a, b);
	return 0;
	
}
void MMax(int a, int b)
{
	int s[20] = { 0 };
	int sum = 0, temp1 = 0, m,k=0;
	int  i = 0;
	if (a > b)
	{
		int temp;
		temp = a;
		a = b;
		b = temp;
	}
	while (b)//将较大数存进数组中(倒着存的)
	{
		s[i++] = b % 10;
		b /= 10;
	}
	for (m = 0; m < i; m++)
	{
		sum = s[m] * a + temp1;//记
		s[k++] = sum % 10;
		temp1 = sum / 10;
	}
	while(temp1)
	{
		s[k++] = temp1%10;
		temp1 /= 10;
	}
	while (k > 0)
	{
		printf("%d", s[k - 1]);
		--k;
	}
}

思考:根据大数相乘的原理写出求自守数的方法

#include<stdio.h>
int main()
{
	char str[100];//存结果
	int a, b;
	long  int result;
	long int MMax(int, int,long int);
	for (long int i = 1; i < 10000; i++)
	{
		result = 0;
		if (i == MMax(i, i, result))
			printf("自守数:%ld\n", i);
	}
	return 0;

}
long int MMax(int a, int b,long int result)
{
	int s[20] = { 0 };
	int sum = 0, temp1 = 0, m, k = 0;
	int  i = 0;
	if (a > b)
	{
		int temp;
		temp = a;
		a = b;
		b = temp;
	}
	while (b)//将较大数存进数组中(倒着存的)
	{
		s[i++] = b % 10;//i存放两个数中大数的位数
		b /= 10;
	}
	for (m = 0; m < i; m++)
	{
		sum = s[m] * a + temp1;//记
		s[k++] = sum % 10;//k存放结果的位数
		temp1 = sum / 10;
	}
	while (temp1)
	{
		s[k++] = temp1 % 10;
		temp1 /= 10;
	}
	//取出与原数相同位数的数返回
	int f, ss = 1;
	for ( f = 0; f <i; f++)
	{
		result = result + s[f]*ss;//语句1
		//result = result*10 + s[f];//语句2
		ss *= 10;
	}
	return result;
}

知识点:
1.若一个数组逆序存放你需要的原数,比如原数为123456,在数组中存成了654321,想要正确的返回原数应采用 1语句的方法,需要设置一个变量初始为1

2.若一个数组正序存放你想要的原数,如原数123456,数组中也是123456,只需用语句2即可

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值