資訊學奧賽一本通(C++版) 第二部分 基礎演算法 第一章 高精度計算
阿新 • • 發佈:2019-01-07
//1307 【例1.3】高精度乘法
//手動模擬乘法運算
//提交,測試點5,答案錯誤,猜測,應該是0的情況,沒考慮
//提供一組測試資料
//輸入:
//123
//0
//輸出:
//0
//考慮了0的情況,修改,提交AC 2017-11-9
//編到這裡,感覺高精度加是高精度演算法的基礎
#include <stdio.h>
#include <string.h>
int a[110],b[110],c[220];
char s[110];
void mul(){
int i,j;
for(i=1;i<=a[0];i++)
for(j=1;j<=b[0];j++){
c[i+j-1]+=a[i]*b[j];
c[i+j]+=c[i+j-1]/10;
c[i+j-1]%=10;
}
c[0]=a[0]+b[0]-1;
if(c[c[0]+1]>0)c[0]+=1;
}
int main(){
int i,len,k;
memset(a,0,sizeof(a)),memset(b,0,sizeof(b)),memset(c,0,sizeof(c));
scanf("%s",s);
len=strlen(s),k=0;
for(i=len-1;i>=0;i--)a[++k]=s[i]-'0';
a[0]=len;
scanf("%s",s);
len=strlen(s),k=0;
for(i=len-1;i>=0;i--)b[++k]=s[i]-'0';
b[0]=len;
if((a[0]==1&&a[1]==0)||(b[0]==1&&b[1]==0))printf("0");
else{
mul();
for(i=c[0];i>=1;i--)printf("%d",c[i]);
}
return 0;
}
//1308 【例1.5】高精除
//基本可以猜到測試資料
//1 分子為0 商為0,餘數為0
//2 分子 分母相等,商為1,餘數為0
//3 在long long 範圍內的分子 分母
//以上三點至少可得30分
//如果是比賽,上述觀點能得部分分
//基本想法是用高精度減,但容易超時
//換思路,
//此文程式碼寫得比較短https://www.cnblogs.com/shenben/p/5878072.html
//學習
//演算法明白後,編寫程式碼,但除錯了70分鐘,樣例通過後,提交 2017-11-10
//提交,測試點3,答案錯誤
//提供一組測試樣例
//輸入:
//1000
//1
//輸出:
//1000
//0
//此題編寫,感覺自個程式碼在到處打補丁,很不順暢。
//修改,提交AC,不過,呢,程式碼全程都是自個編下來的,在編寫過程中再也沒有參考其他,也算是進步吧。
//日後此題應該還會再編寫一遍。
#include <stdio.h>
#include <string.h>
int a[310],b[310],c[310],d[310],t[310];//d商 t臨時陣列
char s[310];
int compare(int a[],int b[]){//a>b 1 a==b 0 a<b -1 高精度 比較大小
int i;
if(a[0]>b[0])return 1;
if(a[0]<b[0])return -1;
if(a[0]==b[0])
for(i=a[0];i>=1;i--)
if(a[i]>b[i])return 1;
else if(a[i]<b[i])return -1;
return 0;
}
void sub(int a[],int b[]){//a>b 高精度減
int i;
for(i=1;i<=b[0];i++){
if(a[i]<b[i]){//借位
a[i]+=10;
a[i+1]--;
}
a[i]-=b[i];
}
i=a[0];
while(a[i]==0)i--;
if(i==0)a[0]=1;//此句寫成if(a[0]==0)a[0]=1;//漏了此句
else a[0]=i;
}
int main(){
int i,len,k,j,q;
memset(a,0,sizeof(a)),memset(b,0,sizeof(b)),memset(d,0,sizeof(d));
scanf("%s",s);
len=strlen(s),k=0;
for(i=len-1;i>=0;i--)a[++k]=s[i]-'0';
a[0]=len;
scanf("%s",s);
len=strlen(s),k=0;
for(i=len-1;i>=0;i--)b[++k]=s[i]-'0';
b[0]=len;
if(a[0]==1&&a[1]==0)printf("0\n0");//0初一其它數的處理
else if(compare(a,b)==0)printf("1\n0");//a==b
else if(compare(a,b)==-1){//a<b
printf("0\n");
for(i=a[0];i>=1;i--)printf("%d",a[i]);
}else{//a>b
d[0]=a[0]-b[0]+1,q=0;//商的位數
for(i=a[0];i>=1;i--){
if(compare(a,b)<=0)break;//此行寫成if(compare(a,b)==-1)break;//新增此行
memset(t,0,sizeof(t)),t[0]=i,k=t[0];//此處寫成t[0]=a[0],//此處寫成k=0//漏了該句 t[0]=a[0];
for(j=b[0];j>=1;j--)t[k]=b[j],k--;//此處寫成t[i+k]=b[j],k++;//此處寫成 for(j=b[0];j>=1;j--)t[i+k]=b[j],k++;
while(compare(a,t)>=0)d[d[0]-q]++,sub(a,t);//此處寫成while(compare(a,t)==1)//此處寫成 while(compare(a,b)==1)
q++;
}
i=d[0];
while(d[i]==0)i--;//前導0的處理
d[0]=i;
for(i=d[0];i>=1;i--)printf("%d",d[i]);
printf("\n");
for(i=a[0];i>=1;i--)printf("%d",a[i]);
}
return 0;
}
//1309 【例1.6】迴文數(Noip1999)
//高精度加演算法,很有信心
//後判斷
//翻轉
//先加
//30步跳出
//仔細看題,發現並不只是十進位制,是N進位制,馬上意識到該題的難度了
//過了一晚之後,再想想,只要把十進位制中的10換成N,並編寫一個列印函式,列印位上的值大於等於10的 即可。
//題目沒有明確位數個數,故陣列均開到500
//樣例通過,提交,未通過,
//因是歷年NOIP普及組 複賽試題,容易得到測試資料
//看了看,確實會比較難過,因為輸入資料中就有16進位制
//馬上對讀取後的資料進行修改處理,題中沒有說輸入資料是否大寫,或是小寫,一併處理了
//再次提交,全未通過,檢視原始輸入輸出資料
//查了 洛谷 P1015 迴文數
//https://www.luogu.org/problemnew/show/1015
//洛谷上通過後,再進行提交,AC,
//http://ybt.ssoier.cn:8088中該題,沒法看,直接參考洛谷裡的題目,按裡面的輸入輸出要求進行提交
//2017-11-10
#include <stdio.h>
#include <string.h>
int N,a[500],b[500],step=0;
char s[500];
void add(int a[],int b[]){
int i;
for(i=1;i<=a[0];i++){
a[i]+=b[i];
a[i+1]+=a[i]/N;
a[i]%=N;
}
if(a[a[0]+1]>0)a[0]+=1;
}
int judge(int a[]){//0非迴文,1迴文
int i;
for(i=1;i<=a[0]/2;i++)
if(a[i]!=a[a[0]-i+1])
return 0;
return 1;
}
void overturn(int a[]){
int i,j=0;
b[0]=a[0];
for(i=a[0];i>=1;i--)
b[++j]=a[i];//此處寫成b[j]=a[i],j++;
}
void print(int a[]){
int i;
for(i=a[0];i>=1;i--)
printf("%d",a[i]);
printf("\n");
}
int main(){
int len,i,k=0;
scanf("%d%s",&N,s);
len=strlen(s);
for(i=len-1;i>=0;i--)//重寫讀入資料的處理
if('0'<=s[i]&&s[i]<='9')
a[++k]=s[i]-'0';
else if('a'<=s[i]&&s[i]<='z')
a[++k]=s[i]-'a'+10;
else if('A'<=s[i]&&s[i]<='Z')
a[++k]=s[i]-'A'+10;
a[0]=len;
while(judge(a)==0){
//printf("1 "),print(a);
overturn(a);
//printf("2 "),print(b);
add(a,b);
//printf("3 "),print(a);
step++;
if(step==31)break;
}
if(step==31)printf("Impossible!");//此處寫成 printf("Impossible");
else printf("STEP=%d",step);//此處寫成 printf("%d",step);
return 0;
}
//手動模擬乘法運算
//提交,測試點5,答案錯誤,猜測,應該是0的情況,沒考慮
//提供一組測試資料
//輸入:
//123
//0
//輸出:
//0
//考慮了0的情況,修改,提交AC 2017-11-9
//編到這裡,感覺高精度加是高精度演算法的基礎
#include <stdio.h>
#include <string.h>
int a[110],b[110],c[220];
char s[110];
void mul(){
int i,j;
for(i=1;i<=a[0];i++)
for(j=1;j<=b[0];j++){
c[i+j-1]+=a[i]*b[j];
c[i+j]+=c[i+j-1]/10;
c[i+j-1]%=10;
}
c[0]=a[0]+b[0]-1;
if(c[c[0]+1]>0)c[0]+=1;
}
int main(){
int i,len,k;
memset(a,0,sizeof(a)),memset(b,0,sizeof(b)),memset(c,0,sizeof(c));
scanf("%s",s);
len=strlen(s),k=0;
for(i=len-1;i>=0;i--)a[++k]=s[i]-'0';
a[0]=len;
scanf("%s",s);
len=strlen(s),k=0;
for(i=len-1;i>=0;i--)b[++k]=s[i]-'0';
b[0]=len;
if((a[0]==1&&a[1]==0)||(b[0]==1&&b[1]==0))printf("0");
else{
mul();
for(i=c[0];i>=1;i--)printf("%d",c[i]);
}
return 0;
}
//1308 【例1.5】高精除
//基本可以猜到測試資料
//1 分子為0 商為0,餘數為0
//2 分子 分母相等,商為1,餘數為0
//3 在long long 範圍內的分子 分母
//以上三點至少可得30分
//如果是比賽,上述觀點能得部分分
//基本想法是用高精度減,但容易超時
//換思路,
//此文程式碼寫得比較短https://www.cnblogs.com/shenben/p/5878072.html
//學習
//演算法明白後,編寫程式碼,但除錯了70分鐘,樣例通過後,提交 2017-11-10
//提交,測試點3,答案錯誤
//提供一組測試樣例
//輸入:
//1000
//1
//輸出:
//1000
//0
//此題編寫,感覺自個程式碼在到處打補丁,很不順暢。
//修改,提交AC,不過,呢,程式碼全程都是自個編下來的,在編寫過程中再也沒有參考其他,也算是進步吧。
//日後此題應該還會再編寫一遍。
#include <stdio.h>
#include <string.h>
int a[310],b[310],c[310],d[310],t[310];//d商 t臨時陣列
char s[310];
int compare(int a[],int b[]){//a>b 1 a==b 0 a<b -1 高精度 比較大小
int i;
if(a[0]>b[0])return 1;
if(a[0]<b[0])return -1;
if(a[0]==b[0])
for(i=a[0];i>=1;i--)
if(a[i]>b[i])return 1;
else if(a[i]<b[i])return -1;
return 0;
}
void sub(int a[],int b[]){//a>b 高精度減
int i;
for(i=1;i<=b[0];i++){
if(a[i]<b[i]){//借位
a[i]+=10;
a[i+1]--;
}
a[i]-=b[i];
}
i=a[0];
while(a[i]==0)i--;
if(i==0)a[0]=1;//此句寫成if(a[0]==0)a[0]=1;//漏了此句
else a[0]=i;
}
int main(){
int i,len,k,j,q;
memset(a,0,sizeof(a)),memset(b,0,sizeof(b)),memset(d,0,sizeof(d));
scanf("%s",s);
len=strlen(s),k=0;
for(i=len-1;i>=0;i--)a[++k]=s[i]-'0';
a[0]=len;
scanf("%s",s);
len=strlen(s),k=0;
for(i=len-1;i>=0;i--)b[++k]=s[i]-'0';
b[0]=len;
if(a[0]==1&&a[1]==0)printf("0\n0");//0初一其它數的處理
else if(compare(a,b)==0)printf("1\n0");//a==b
else if(compare(a,b)==-1){//a<b
printf("0\n");
for(i=a[0];i>=1;i--)printf("%d",a[i]);
}else{//a>b
d[0]=a[0]-b[0]+1,q=0;//商的位數
for(i=a[0];i>=1;i--){
if(compare(a,b)<=0)break;//此行寫成if(compare(a,b)==-1)break;//新增此行
memset(t,0,sizeof(t)),t[0]=i,k=t[0];//此處寫成t[0]=a[0],//此處寫成k=0//漏了該句 t[0]=a[0];
for(j=b[0];j>=1;j--)t[k]=b[j],k--;//此處寫成t[i+k]=b[j],k++;//此處寫成 for(j=b[0];j>=1;j--)t[i+k]=b[j],k++;
while(compare(a,t)>=0)d[d[0]-q]++,sub(a,t);//此處寫成while(compare(a,t)==1)//此處寫成 while(compare(a,b)==1)
q++;
}
i=d[0];
while(d[i]==0)i--;//前導0的處理
d[0]=i;
for(i=d[0];i>=1;i--)printf("%d",d[i]);
printf("\n");
for(i=a[0];i>=1;i--)printf("%d",a[i]);
}
return 0;
}
//1309 【例1.6】迴文數(Noip1999)
//高精度加演算法,很有信心
//後判斷
//翻轉
//先加
//30步跳出
//仔細看題,發現並不只是十進位制,是N進位制,馬上意識到該題的難度了
//過了一晚之後,再想想,只要把十進位制中的10換成N,並編寫一個列印函式,列印位上的值大於等於10的 即可。
//題目沒有明確位數個數,故陣列均開到500
//樣例通過,提交,未通過,
//因是歷年NOIP普及組 複賽試題,容易得到測試資料
//看了看,確實會比較難過,因為輸入資料中就有16進位制
//馬上對讀取後的資料進行修改處理,題中沒有說輸入資料是否大寫,或是小寫,一併處理了
//再次提交,全未通過,檢視原始輸入輸出資料
//查了 洛谷 P1015 迴文數
//https://www.luogu.org/problemnew/show/1015
//洛谷上通過後,再進行提交,AC,
//http://ybt.ssoier.cn:8088中該題,沒法看,直接參考洛谷裡的題目,按裡面的輸入輸出要求進行提交
//2017-11-10
#include <stdio.h>
#include <string.h>
int N,a[500],b[500],step=0;
char s[500];
void add(int a[],int b[]){
int i;
for(i=1;i<=a[0];i++){
a[i]+=b[i];
a[i+1]+=a[i]/N;
a[i]%=N;
}
if(a[a[0]+1]>0)a[0]+=1;
}
int judge(int a[]){//0非迴文,1迴文
int i;
for(i=1;i<=a[0]/2;i++)
if(a[i]!=a[a[0]-i+1])
return 0;
return 1;
}
void overturn(int a[]){
int i,j=0;
b[0]=a[0];
for(i=a[0];i>=1;i--)
b[++j]=a[i];//此處寫成b[j]=a[i],j++;
}
void print(int a[]){
int i;
for(i=a[0];i>=1;i--)
printf("%d",a[i]);
printf("\n");
}
int main(){
int len,i,k=0;
scanf("%d%s",&N,s);
len=strlen(s);
for(i=len-1;i>=0;i--)//重寫讀入資料的處理
if('0'<=s[i]&&s[i]<='9')
a[++k]=s[i]-'0';
else if('a'<=s[i]&&s[i]<='z')
a[++k]=s[i]-'a'+10;
else if('A'<=s[i]&&s[i]<='Z')
a[++k]=s[i]-'A'+10;
a[0]=len;
while(judge(a)==0){
//printf("1 "),print(a);
overturn(a);
//printf("2 "),print(b);
add(a,b);
//printf("3 "),print(a);
step++;
if(step==31)break;
}
if(step==31)printf("Impossible!");//此處寫成 printf("Impossible");
else printf("STEP=%d",step);//此處寫成 printf("%d",step);
return 0;
}