高精度大数(超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中的方式即可
四位数,五位数同理即可