1. 程式人生 > >大數的快速求餘演算法

大數的快速求餘演算法

大數的求餘,相加,相減演算法

  • A plus B+:
    Now give you two positive integers, A, B, and C. Please count A plus B, then modulo C.

Input

Input will consist of multiple problem instances. The first line of the input will contain a single integer indicating the number of problem instances.
Each instance will consist of a single line of 0< A~ ~B~ ~C<10^40

Output

For each problem instance, output a single line containing the answer.

Sample input

2
1 2 100
5 6 10

Sample output

3
1
  • 在實際寫題的時候有意避過了去模擬的過程,不過做完之後還是覺得有必要模擬一波。就花了一下午時間去寫這個東東。
  • 實際大數的求餘數演算法,就是花時間去寫,也沒有多難。判斷倆個數的大小,我採用的是相減。算出結果。
#include <bits/stdc++.h>

using namespace std;

void
big_plus(int numa[],int numb[]);//大數的加法,實現是從末尾來存放個位,然後依次遞推 void big_mod(int numa[],int numb[]);//大數的求餘演算法,實際實現是減法,當位數相差比較大時,先減去一個大倍數的b,減少演算法上面的時間消耗 void init(int a[],int b[],int c[],char ca[],char cb[],char cc[]);//資料初始化 void restore(int numa[],char a[]);//將字串,儲存到陣列中 bool judge(int a[],int b[]);//判斷倆個大數的大小,如果相差超過2位,就用a-n*b,n是a和b的相差的長度-1。
int main() { int N; cin>>N;//N組測試樣例 while(N--) { char a[100],b[100],c[100],flag=0;//flag判斷是否全部是0 int numa[100],numb[100],numc[100];//實際測試50大小的陣列,並不能滿足題目要求,理論上10^20+10^20足夠了,emmm還是申請了100大小的 init(numa,numb,numc,a,b,c); cin>>a>>b>>c; restore(numa,a); restore(numb,b); restore(numc,c); big_plus(numa,numb);//其實也可以相加之前求餘數,不過簡化之後的求餘函式就沒多少必要了 big_mod(numa,numc); for(int i=0;i<100;i++)//求掉前導0 { if(numa[i]!=0) flag=1; if(flag)cout<<numa[i]; } if(flag==0)cout<<0; cout<<endl; } return 0; } void init(int a[],int b[],int c[],char ca[],char cb[],char cc[]) { for(int i=0;i<100;i++) { a[i]=b[i]=c[i]=0; ca[i]=cb[i]=cc[i]='#';//#作為資料輸入的結束判斷 } } void restore(int numa[],char a[]) { int i=0; for(i=strlen(a)-1;a[i]=='#';i--); for(int j=99;i>=0;i--,j--)//將個位放在陣列末尾,然後依次向前遞推。 numa[j]=a[i]-48; } bool judge(int a[],int b[]) { int lena=0,lenb=0,flag[2]={0}; for(int i=0;i<=99;i++)//先求出倆個大數的長度 { if(a[i]!=0&&flag[0]==0) { lena=100-i; flag[0]=1; } if(b[i]!=0&&flag[1]==0) { lenb=100-i; flag[1]=1; } } if(lena>lenb)//大數比較大時,開始演算法超時也是在這裡。比如計算123456789123456789 123456789123456789 2的時候,不知道要跑幾個小時。 { int bit=lena-lenb-1,c[100]; memset(c,0,sizeof(c)); for(int i=99-lenb;i<=99;i++) { c[i-bit]=b[i]; } for(int i=99,tmp=0;i>=0;i--) { tmp=a[i]-c[i]; if(tmp<0) { tmp+=10; a[i-1]-=1; } a[i]=tmp; } return true; } else if(lena<lenb) { return false; } else if(lena==lenb) { for(int i=100-lena;i<100;i++) { if(a[i]>b[i])return true; else if(a[i]<b[i])return false; } return true;//全部都相等也是要求餘的,比如:1 2 3結果是0 } } void big_plus(int numa[],int numb[])//大數相加,從末尾開始,注意進位就好了 { for(int i=99,tmp=0;i>=0;i--) { tmp=numa[i]+numb[i]; while(tmp>=10) { numa[i-1]+=1; tmp-=10; } numa[i]=tmp; } } void big_mod(int a[],int b[])//大數求餘 { while(judge(a,b)) { for(int i=99,tmp=0;i>=0;i--) { tmp=a[i]-b[i]; if(tmp<0) { tmp+=10; a[i-1]-=1; } a[i]=tmp; } } }
  • 還有Java和python的就不給了,Java和python都有大數型別,就像作弊了一樣,直接跳過模擬過程。