高精度大数(超long long)取余原理及模板

高精度大数取余普通版

大数取余的原理: 从字符串的首位开始,对其取余,并将余数存起来与后一位连接(非相加),继续取余。
其实就是模拟我们手算时的过程

例如 562对3取余
取首位 5 % 3=2
取第二位 并加上之前的余数 (2* 10+6)%3=2
取第三位 同样加上之前的余数 (2*10+2)%3=4
得到 562%3=4
long long ans=0;
for (int i = 0; i < num.size(); i++) {
	ans=(ans*10+num[i]-'0')%mod;//mod是需要取余的数,ans为结果
}

在这里插入图片描述

高精度大数取余快速版(局部有序,整体有序)

1

一位一位取对于一些题目来说可能有点慢,那么采用三位,四位取余的方法

char k[105];
	int a[40];
	scanf("%s",k);//输入字符串
	int len=strlen(k)-1;
	int ans=0;
	for(int i=0; i<=len; i=i+3) {
		int cnt=0;
		int ff=0;
		for(int j=0; j<=2; j++) {
			if(i+j>len)
				break;
			cnt=cnt*10+k[i+j]-'0';
			if(ff==0) {
				ans++;
				ff=1;
			}
		}
		a[ans]=cnt;//三位一个存储到数组a
	}

这里采用局部有序,整体有序的方法
在这里插入图片描述

int cnt=0,xx=0;
	for(int j=1; j<=ans; j++) {
		if(a[j]<10 &&j==ans)
			xx=10;
		else if(a[j]<100 &&j==ans)
			xx=100;
		else
			xx=1000;
		cnt=(cnt*xx+a[j])%mod;
	}
	cout<<cnt;

发现最后一个a[i]可能是一位数,二位数,三位数,所以模板也要做出修改

2

会发现这样写代码有点繁琐了,能不能做出一点修改使得代码变得更加简洁呢

char k[105];
	int a[40];
	scanf("%s",k);//输入字符串
	int len=strlen(k)-1;
	int ans=0;
	int top=(len+1)%3;
	int cnt1=0;
	for(int i=0;i<top;i++){
		cnt1=cnt1*10+k[i]-'0';
	}
	a[++ans]=cnt1;
	for(int i=top; i<=len; i=i+3) {
		int cnt=0;
		int ff=0;
		for(int j=0; j<=2; j++) {
			if(i+j>len)
				break;
			cnt=cnt*10+k[i+j]-'0';
			if(ff==0) {
				ans++;
				ff=1;
			}
		}
		a[ans]=cnt;//三位一个存储到数组a
	}

在这里插入图片描述

int cnt=0,xx=1000;
	for(int j=1; j<=ans; j++) {
		cnt=(cnt*xx+a[j])%mod;
	}
	cout<<cnt;

此时只要更改一下字符串存储到数组a中的方式即可

四位数,五位数同理即可

posted @ 2021-04-19 21:30  cheems~  阅读(374)  评论(0编辑  收藏  举报