高精度阶乘(今天真的只能搞定这一题今天累鼠了)

25 阅读2分钟

题目一

image.png

基本思路

1.四位数阶乘结果肯定爆掉long long 了,一定是高精度乘法;
2.我们发现没一个数字都是小的数字,但是累积结果是大数字,所以很难用字符串,考虑不用字符串;
3.我们依然要用三个数组,一个a[]用来存结果,b[]存乘数(很大),c[]用来存临时乘积;强调:一定要有c这个数组,因为C一直在参加计算,会覆盖掉原来的值,最后把c的值赋给a就行

关键点

1.c数组赋值a数组一定都要保持低位在前;
2.模块那里每次都从0开始遍历看起来会重复,但其实数据没重复,重复的只是过程

我的代码

#include<stdio.h>
#include<string.h>

int main()
{
	int t;
	scanf("%d",&t);
	
	//要输出数字组数为t 
	while(t--){
		int a[5005]={1},b[5005],c[10010];//a数组保存阶乘结果,b数组保存乘数,c数组保存a*b临时结果 
		int n,target;//定义 
		scanf("%d %d",&n,&target);
		
		int lenA=1;
	    int x,i;
		int temp;
		int lenB,lenC;//这两个长度在后面的乘法模块要用到 
		
		for(x=2;x<=n;x++){
			temp=x;//这里用一个临时变量存 
			lenB=0;
			while(temp>0){
				b[lenB++] = temp % 10; //确保b数组每一个数都是个位数 
				temp /= 10; //temp每一位数字都要变成b数组一个数单元 
			}
	
			int j;
			memset(c, 0, sizeof(c));//这里是初始化c数组为0 ,相比遍历赋值更简单 
			for(i=0;i<lenA;i++){
				//下面这一块高精度乘法经典模块 
				for(j=0;j<lenB;j++){
					c[i+j]+=a[i]*b[j];
				}
				
				for(j=0;j<lenB;j++){
					c[i+j+1]+=c[i+j] / 10;
					c[i+j] %= 10;
				}
			}
			
			int lenC=lenA+lenB;
			while(lenC>1 && c[lenC-1]==0){
				lenC--;//去掉前导零 
			}
			
			for(i=0;i<lenC;i++){
				a[i]=c[i];//这里千万不要倒着赋值,只有输出的时候需要倒过来。保持低位在前。 
			}
			lenA=lenC;
	}
		int cnt=0;
		for(i=0;i<lenA;i++){
			if(a[i]==target) cnt++;
		}
		
		printf("%d\n",cnt);
	}
			

	return 0;
        //写完这一篇了,我感觉让我做我还是做不出来,我明天会再来尝试做这道题,结果我会写到明天文章
}