大數的快速求餘演算法
阿新 • • 發佈:2019-02-04
大數的求餘,相加,相減演算法
- 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都有大數型別,就像作弊了一樣,直接跳過模擬過程。