高精度大数取余普通版
大数取余的原理: 从字符串的首位开始,对其取余,并将余数存起来与后一位连接(非相加),继续取余。
其实就是模拟我们手算时的过程
例如 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中的方式即可
四位数,五位数同理即可