菜鸟BIT程序设计课A题日志第二周

来源:互联网 发布:ubuntu 交叉编译 编辑:程序博客网 时间:2024/06/18 05:10

从第一周开始我就有那么点因虚荣而后怕——这日志接不下去不悲剧了。果然,这一周题的难度飙升程度对于菜鸟我来说实在有点大。

第五题一点都不未雨绸缪的高精度运算。

算法到处都看得到,而且只是加减与正整数,所以说弱爆了啊!!!一点都不未雨绸缪搞得第七题重用就是水中月。但是开题之前在软院做得时候还是调了一天(可惜软院现在关闭了哇啊,悲催没有狠下心多做点当时,不过现在还是残留着题和讨论区~你懂的):

 

计算机所能完成的一个基本功能就是完成数据的计算,譬如加法、减法等等。但是在任何一种计算机上,计算中能够使用的数字都是有一定范围的,超过了范围,就没法得到精确的结果。

你现在接受了一个任务,要编写一个高精度计算器的核心部分。所谓高精度计算器,就是可以计算很大很大的数据的计算器。而你所需要编写的程序,就是真正完成高精度加法和高精度减法运算的两个函数,因为程序其它的部分已经由别人编写好了。

函数的输入、输出接口也已经定义完成,譬如 plus() 函数,它有三个参数 a、b 和 c,都是 char * 类型。a 和 b分别是参加运算的两个整数,而 c 用来存放运算的结果。所有的数字都是以字符串的形式保存的。

注意,只需提交你自己编写的两个函数。

输入

输入的每一行是两个十进制的正整数和一个运算符,每个整数可以由最多 500 个数字组成。运算符可以是加号或者减号。

输出

对应着输入的每一行数据,输出计算的结果,每个结果占一行。

#include <stdio.h>
#include <string.h>

void plus(char *a, char *b, char *c);
void minus(char *a, char *b, char *c);

int main()
     
    chara[1000];
    charb[1000];
    charc[1000];
    chars[2];

    while(scanf("%s %s %s\n", a, s, b) == 3) {
       if (s[0] == '+') {
           plus(a, b, c);
       } else if (s[0] == '-') {
           minus(a, b, c);
       }
       printf("%s\n", c);
    }

    return0;
}

 

void plus(char *a, char *b, char *c){
 int i=0,j=0,k=0,max=0,min=0,temp=0;
 char *pmax,*pmin;
 memset(c,0,sizeof(c));
 c[0]='0';
 max=strlen(a);
 min=strlen(b);
 if (max<min){
  pmax=b;
  pmin=a;
  temp=max;
  max=min;
  min=temp;
 }
 else{
  pmax=a;
  pmin=b;
 }
 for(i=min-1,j=max-1,k=max;i>=0;i--,j--,k--)
  c[k]=pmin[i]-'0'+pmax[j];
 if(j>=0)
  for(;j>=0;j--,k--)
   c[k]=pmax[j];
  for(i=max;i>=0;i--){  
   if(c[i]>'9')
   {
    c[i]=c[i]-10;
    c[i-1]++;
   }
  }
       if (c[0]=='0'){  
           for(i=1;i<=max;i++)  
               c[i-1]=c[i];   
           c[i-1]='\0';   
        
       else{   
           for(i=0;i<=max;)   
    i++;
           c[i]='\0'; 
  }
  for(i=0;i<strlen(c);i++){
   if(c[i]!='0')
    break;
   max=strlen(c)-i;
  }
  if(c[0]=='0'){
   for(j=0;j<max;j++,i++){
    c[j]=c[i];
   }
  }
}
void minus(char *a, char *b, char *c){
 int i,j,la,lb;
 for(i=0;i<strlen(a);i++){
  if(a[i]!='0')
   break;
  la=strlen(a)-i;
 }
 if(a[0]=='0'){
  for(j=0;j<la;j++,i++){
   a[j]=a[i];
  }
  }
 for(i=0;i<strlen(b);i++){
  if(b[i]!='0')
   break;
  la=strlen(b)-i;
 }
 if(b[0]=='0'){
  for(j=0;j<la;j++,i++){
   b[j]=b[i];
  }
  }
 la=strlen(a);
 lb=strlen(b);
 if(la>lb||(la==lb&&strcmp(a,b)>=0)){
  for(i=la-1,j=lb-1;j>=0;i--,j--)
   a[i]=a[i]-(b[j]-'0');
  for(i=la-1;i>=0;i--)
   if(a[i]<'0'){
    a[i]+=10;
    a[i-1]--;
   }
   i=0;
   while(a[i]=='0')
    i++;
   if(a[i]=='\0'){
    c[0]='0';
    c[1]='\0';
   }
   else{
    for(j=0;a[i]!='\0';i++,j++)
     c[j]=a[i];
    c[j]='\0';
   }
 }
 else{
  for(i=la-1,j=lb-1;i>=0;i--,j--)
   b[j]=b[j]-(a[i]-'0');
  for(j=lb-1;j>=0;j--)
   if(b[j]<'0'){
    b[j]+=10;
    b[j-1]--;
   }
   j=0;
   while(b[j]=='0')
    j++;
   i=1;
   c[0]='-';
   for(;b[j]!='\0';i++,j++)
    c[i]=b[j];
   c[i]='\0';
 }

}

第六题 开始唬人的大整数因子

第一眼就感觉这题是要传说中得高精度除法么~从紧张到抓狂再到惆怅的过程差不多的时候才发现诶~小学老师貌似讲过一点整除技巧神马后三位数字相加能被3整除的数就能被三整除云云~果断百度出所有方法顿时山无棱天地合发现模拟题…,这里的问题就是7,于是采用了“若一个整数的个位数字截去,再从余下的数中,减去个位数的2倍,如果差是7的倍数,则原数能被7整除。如果差太大或心算不易看出是否7的倍数,就需要继续”的方法,不是最好,但也易行。

描述

已知正整数 k 满足 2<=k<=9,现给出长度最大为 30位的十进制非负整数 c,求所有能整除 c 的 k。

输入

输入从文件 bignum.in读取。若干个非负整数 c,c 的位数 <= 30。每行一个 c,当 c=-1时中止(不要对-1进行计算!)

输出

请把结果保存到 bignum.out中,每一个 c 的结果占一行。

1) 若存在满足 c % k == 0 的 k,输出所有这样的 k,中间用空格隔开,最后一个 k 后面有空格。
2) 若没有这样的 k 则输出 "none"。

#include"stdio.h"
#include"stdlib.h"
#include"string.h"
void minus(char *a, char *b, char *c){
 int i,j,la,lb;
 la=strlen(a);
 lb=strlen(b);
 for(i=la-1,j=lb-1;j>=0;i--,j--)
  a[i]=a[i]-(b[j]-'0');
 for (i=la-1;i>=0;i--)
  if(a[i]<'0'){
   a[i]+=10;
   a[i-1]--;
  }i=0;
  while (a[i]=='0')
   i++;
  if (a[i]=='\0'){
   c[0]='0';
   c[1]='\0';
  }
  else{
   for(j=0;a[i]!='\0';i++,j++)
    c[j]=a[i];
   c[j]='\0';
  
}
int main(){
 intlen=0,length=0,i=0,j=0,total=0,la2,la3,flag6,ans=0;
 charc[50]="",k[50]="",rediv[50]="",bit[20]="",temp[50]="";
 FILE *fp1,*fp2;
 fp1=fopen("bignum.in","r");
 fp2=fopen("bignum.out","w");
 while(1){
  fgets(c,50,fp1);
  len=strlen(c)-1;
  if(c[0]!='-')
  {
   i=0;total=0;flag6=0;  
   if((c[len-1]-'0')%2==0){
    k[i]='2';
    k[i+1]='';
    i+=2;
    flag6++;
   }
   for(j=0;j<len;j++)
    total+=(c[j]-'0');
   if(total%3==0){
    k[i]='3';
    k[i+1]='';
    i+=2;
    flag6++;
   }
   if(len>=2)
   la2=(c[len-1]-'0')+10*(c[len-2]-'0');
   elsela2=(c[len-1]-'0');
   if(la2%4==0){
    k[i]='4';k[i+1]='';i+=2;
   }
   if((c[len-1]-'0')%5==0||(c[len-1]=='0')){
    k[i]='5';k[i+1]='';i+=2;
   }
   if(flag6==2){
    k[i]='6';k[i+1]='';i+=2;
   }
   length=len;
   for(j=0;j<len;j++){
    rediv[j]=c[j];
   }
   while(length>2){
    for(j=0;j<length-1;j++){
     temp[j]=rediv[j];
    
    bit[1]=(rediv[length-1]-'0')*2+'0';
    bit[0]=(rediv[length-1]-'0')*2/10+'0';
    minus(temp,bit,rediv);
    length=strlen(rediv);
    memset(temp,0,sizeof(temp));
   }
   if(length==2)
   ans=rediv[1]-'0'+(rediv[0]-'0')*10;
   else
    ans=rediv[0]-'0';
   if(ans%7==0){
    k[i]='7';k[i+1]='';i+=2;
   }
   if(len>=3)
    la3=(c[len-1]-'0')+10*(c[len-2]-'0')+100*(c[len-3]-'0');
   elseif(len==2) la3=(c[1]-'0')+10*(c[0]-'0');
   elseif(len==1) la3=(c[1]-'0');
   if(la3%8==0){
    k[i]='8';k[i+1]='';i+=2;
   }
   if(total%9==0){
    k[i]='9';k[i+1]='';i+=2;
   }
   if(strlen(k)==0)
   {fputs("none\n",fp2);continue;}
   else
   {k[i-1]='\n';
   fputs(k,fp2);}
  }
  else
   break;
  memset(k,0,sizeof(k));
  memset(c,0,sizeof(c));
  memset(bit,0,sizeof(bit));
  memset(rediv,0,sizeof(rediv));
  memset(temp,0,sizeof(temp));
 }
 return 0;
}

第三题 十分纠结的波兰式

这题还真是从始至终都没思路~因为各路大神已经在我做题之前已经探路了…诶~说实话虽然自己也想了好久~但还是在无果之下抵不住大神的算法诱惑~果断递归走起~

但是最初最纠结的还是恨铁不成钢的加减高精度啊~

此处省略N个字~因为极度排斥为了正负号完全重写高精度,于是终于找到了偷懒法:

ab均为非负整数)加法有四种输入情况(中缀写法):a + b ,-a+-b, -a + b,a+-b, 第二种可以转化为-( a +b)的加法,后两种可以分别化成b-a, a-b的减法~在加法的函数里判断下调用即可~而减法则可以如法炮制~甚至可以在-a - -b的时候调用减法自身变成b – a 的减法~。于是又在纠结递归参数传递问题,因为双目运算需要两个返回值,而前一个返回的数组名和后一个返回的相同就覆盖了~于是在判断进入每个运算后都设两个数组,各存一个,最后运算的结果一直存在从始至终的结果数组中,提交……哇!倒二。纠结良久询问斌神~果断得知还有输入-0直接输出0……判断完果断A啊哈。

背景

以下是几个标准的表达式:

  • 5 * 2 +-3
  • 5 * (2 +-3)
  • 5 + ((-4* -5) + (((5 + (6 - 2)) * 7 + ((4 + 2) * (3 - 1))))

与之等价的波兰表达式为

  • + * 5 2-3
  • * 5 + 2-3
  • + 5 + *-4 -5 + * + 5 - 6 2 7 * + 4 2 - 3 1

在普通的表达式中,符号是位于运算对象之间的,而在波兰表达式中,运算符号位于参与运算的对象之前。

波兰式在计算中的价值在于它不需要使用括号,之所以如此是由于波兰式的操作符的先后顺序是明确的。

如果我们用 P 表示波兰表达式,用O 表示操作符,用D表示数字,则可以将波兰表达式定义为 P = O P PP =D

任务

编写程序计算波兰表达式的值。

输入

输入第一行是一个整数,表示输入文件中共有几个波兰式,之后每一行是一个波兰表达式。

每个表达式包含数字和二元操作符 +-*,操作数和运算结果都在[-101000, 101000] 之间。

可以假设每行的数据(运算符号和数字)总共不超过 100 个。

输入请从文件 polan.in中读取

输出

对每个表达式输出其值,并保存到 polan.out中

#include"stdio.h"
#include"string.h"
#include"stdlib.h"
char * minus(char *b, char *a,char *temp);
char * movefore(char *ab){
 int i=0,len=0;
 len=strlen(ab);
 for(i=0;i<len;i++){
  ab[i]=ab[i+1];
 }
 return ab;
}
char * moveback(char *ab){
 int i=0,len=0;
 len=strlen(ab);
 for(i=len;i>0;i--){
  ab[i]=ab[i-1];
 }
 ab[0]='-';
 return ab;
}
char * plus(char *b, char *a,char *temp){
 int i=0,j=0,k=0,max=0,min=0;
 char *pmax,*pmin;
 if(*a=='-'&&*b!='-'){
  returnminus(movefore(a),b,temp);
 }
 elseif(*a!='-'&&*b=='-'){
  returnminus(movefore(b),a,temp);
 }
 max=strlen(a)>=strlen(b)?strlen(a):strlen(b);
 min=strlen(a)<strlen(b)?strlen(a):strlen(b);
 pmax=strlen(a)<strlen(b)?b:a;
 pmin=strlen(a)<strlen(b)?a:b;
 if(*a!='-'&&*b!='-'){
  temp[0]='0';
  for(i=min-1,j=max-1,k=max;i>=0;i--,j--,k--)
   temp[k]=pmin[i]-'0'+pmax[j];
  if(j>=0)
   for(;j>=0;j--,k--)
    temp[k]=pmax[j];
   for(i=max;i>=0;i--){ 
    if(temp[i]>'9')
    {
     temp[i]=temp[i]-10;
     temp[i-1]++;
    }
   }
   if(temp[0]=='0'){  
    for(i=1;i<=max;i++)  
     temp[i-1]=temp[i];   
    temp[i-1]='\0';   
    
   else{   
    for(i=0;i<=max;)   
     i++;
    temp[i]='\0';
   }
   returntemp;
 }
 elseif(*a=='-'&&*b=='-'){
  temp[0]='-';
  temp[1]='0';
  for(i=min-1,j=max-1,k=max;i>0;i--,j--,k--)
   temp[k]=pmin[i]-'0'+pmax[j];
  if(j>0){
   for(;j>0;j--,k--)
    temp[k]=pmax[j];
  }
  for(i=max;i>1;i--){ 
   if(temp[i]>'9'){
    temp[i]=temp[i]-10;
    temp[i-1]++;
   }
  }
  if(temp[1]=='0'){  
   for(i=2;i<=max;i++)  
    temp[i-1]=temp[i];   
   temp[i-1]='\0';
   
  //temp[max+1]='\0'; 
  if((strlen(temp)==2)&&(temp[1]=='0')){
   temp[0]='0';temp[1]='\0';
  }
  return temp;
 }
}
char * minus(char *b, char *a,char *temp){
 int i,j,la,lb;
 if(*a=='-'&&*b!='-'){
  returnplus(moveback(b),a,temp);
 }
 elseif(*a!='-'&&*b=='-'){
  returnplus(movefore(b),a,temp);
 }
 elseif(*a=='-'&&*b=='-'){
  returnminus(movefore(a),movefore(b),temp);
 }
 elseif(*a!='-'&&*b!='-'){
  la=strlen(a);
  lb=strlen(b);
  if(la>lb||(la==lb&&strcmp(a,b)>=0)){
   for(i=la-1,j=lb-1;j>=0;i--,j--)
    a[i]=a[i]-(b[j]-'0');
   for(i=la-1;i>=0;i--)
    if(a[i]<'0'){
     a[i]+=10;
     a[i-1]--;
    }i=0;
    while(a[i]=='0')
     i++;
    if(a[i]=='\0'){
     temp[0]='0';
     temp[1]='\0';
    }
    else{
     for(j=0;a[i]!='\0';i++,j++)
      temp[j]=a[i];
     temp[j]='\0';
    }
  }
  elseif(strlen(b)==2&&*(b+1)=='0'){
   temp[0]='0';temp[1]='\0';
  }
  else{
   for(i=la-1,j=lb-1;i>=0;i--,j--)
    b[j]=b[j]-(a[i]-'0');
   for(j=lb-1;j>=0;j--)
    if(b[j]<'0'){
     b[j]+=10;
     b[j-1]--;
    }
    j=0;
    while(b[j]=='0')
     j++;
    
    temp[0]='-';
    for(i=1;b[j]!='\0';i++,j++)
     temp[i]=b[j];
    temp[i]='\0';
  }
  return temp;
 }
}
char *mul(char *sa,char *sb,char *temp){
 int la=0,lb=0,max=0,pmax=0,i=0,j=0,pm=0;
 char stemp[3000]="";
 if(*sa=='0'||*sb=='0'||(*(sa+1)=='0'&&*sa=='-')||(*(sb+1)=='0'&&*sb=='-')){
  temp[0]='0';
 }
 else{
  la = strlen(sa);
  lb = strlen(sb);
  pm=pmax=max=2*(la>lb?la:lb);
  for(i=la-1;i>=0;i--){
   for(j=lb-1;j>=0;j--){
    if(sa[i]!='-'&&sb[j]!='-'){
     stemp[pmax-1]+=(sa[i]-'0')*(sb[j]-'0');
     if(stemp[pmax-1]>9){
      stemp[pmax-2]+=stemp[pmax-1]/10;
      stemp[pmax-1]%=10;
     }pmax--;
    }
   }
   pm--;
   pmax=pm;
  }
  for(pmax=0;pmax<max;pmax++){
   if(stemp[pmax]!='\0')
    break;
  
  if((*sa!='-'&&*sb!='-')||(*sa=='-'&&*sb=='-')){
   for(i=0;pmax<max;i++,pmax++){
    temp[i]=stemp[pmax]+'0';
   }temp[i]='\0';
  }
  else{
   for(i=1;pmax<max;i++,pmax++){
    temp[i]=stemp[pmax]+'0';
   }
   temp[0]='-';
  }
 }
 return temp;
}
char *get(char * str){
 scanf("%s",str);
 if(strlen(str)==2&&str[1]=='0'&&str[0]=='-'){
  str[0]='0';str[1]='\0';
  return str;
 }
 elseif((str[0]=='+'||str[0]=='-'||str[0]=='*')&&strlen(str)==1){
  if(str[0]=='+'){
   chars1[10000]="",s2[10000]="";
   return plus(get(s1),get(s2),str);
  }
  if(str[0]=='-'){
   chars1[10000]="",s2[10000]="";
   return minus(get(s1),get(s2),str);
  }
  if(str[0]=='*'){
   chars1[10000]="",s2[10000]="";
   returnmul(get(s1),get(s2),str);
  }
 }
 else
  return str;
}
int main(){
 int times=0,n=0;
 FILE *fp1,*fp2;
 char t[10000]="";
 fp1=freopen("polan.in","r",stdin);
 fp2=freopen("polan.out","w",stdout);
 scanf("%d",&times);
 for(n=0;n<times;n++){
  puts(get(t));
  memset(t,'\0',sizeof(t));
 }
 return 0;
}

第四题 RP至上的斐波那契

又是一题大神铺路的题~于是照着把1~1000位的所有斐波那契全部存起~到时查询使用的大众式方法,交上~哇了最后两个…纠结良久~琛神路过~几秒看出最初读取一行目标数列的数组太抠门了,只开了1001~改完果断……只剩最后一个WA…于是从不甘不愿到泪流满面四出乱改~也不知如何就在那绝望的边缘随意一交~RP就这样爆发了~:

Fibonacci 数列有如下特点:其第 1 , 2项均为 1 , 1 。从第 3 个数开始,该数是其前两个数之和 . 即 :

  • F1=1 (n=1)
  • F2=1 (n=2)
  • Fn=Fn-1+Fn-2 (n>=3)

请你编写一个函数 fun ,它的功能是:对于一个给定的 数( N ), 求不大于 N 的最大 Fibonacci 数。

输入

输入从 fibo.in 中读取,它的第一行是一个正整数,表示下面有几组数据需要计算。之后的每一行是一个数据 N ,其中 1=< N <= 101000

输出

对应输入的每一行,输出一个不大于 N 的最大 Fibonacci 数,并把结果保存到 fibo.out 中。

char fib[5000][1100];
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
void plus(char *a, char *b, char *c){
 int i=0,j=0,k=0,max=0,min=0;
 char *pmax,*pmin;
 max=strlen(b);
 min=strlen(a);
 pmax=b;
 pmin=a;
 if((max==min)&&(*a+*b-'0'>='9')){
  *c='0';
  for(i=min-1,j=max-1,k=max;i>=0;i--,j--,k--)
   *(c+k)=pmin[i]-'0'+pmax[j];
  if(j>=0)
   for(;j>=0;j--,k--)
    *(c+k)=pmax[j];
   for(i=max;i>=0;i--){  
    if(*(c+i)>'9'){
     *(c+i)=*(c+i)-10;
     *(c+i-1)+=1;
    }
   }
   if(*c=='0'){
    for(i=1;i<=max;i++)  
     *(c+i-1)=*(c+i);
    *(c+i-1)='\0';   
    
   else
    *(c+max+1)='\0';
 }
 else{
  for(i=min-1,j=max-1,k=max-1;i>=0;i--,j--,k--)
   *(c+k)=pmin[i]-'0'+pmax[j];
  if(j>=0)
   for(;j>=0;j--,k--)
    *(c+k)=pmax[j];
   for(i=max;i>=0;i--){  
    if(*(c+i)>'9'){
     *(c+i)=*(c+i)-10;
     *(c+i-1)+=1;
    }
   }*(c+max)='\0';
 }
}
int main(){
 intcount=0,times=0,i=0,j=0,t=0,flag=0,len=0,length=0;
 char *F1,*F2,*Fn,aim[1100]="";
 memset(fib,'\0',sizeof(fib));
 FILE *fp1,*fp2;
 fp1=freopen("fibo.in","r",stdin);
 fp2=freopen("fibo.out","w",stdout);
 fib[0][0]='1';fib[1][0]='1';
 F1=&fib[0][0];F2=&fib[1][0];
 Fn=&fib[2][0];
 for(count=0;count<=4980;++count){
  plus(F1,F2,Fn);
  F1=F2;
  F2=Fn;
  Fn+=1100;
 }
 scanf("%d",&times);
 for(count=0;count<times;++count){
  scanf("%s",aim);
  length=strlen(aim);
  for(i=0;i<4980;i++){
   len=strlen(fib[i]);
   if(len>=length-1)
    break;
  }
  flag=0;
  for(t=0;t<20;t++,i++){
   len=strlen(fib[i]);
   if(len==length){
    for(j=0;j<len;j++){
     if(fib[i][j]>aim[j]){
      flag=1;
      break;
     }
     elseif(fib[i][j]<aim[j])
      break;
    }
   }
   if(flag==1){
    puts(fib[i-1]);
    break;
   }
   if(len>length){
    puts(fib[i-1]);
    break;
   }
  }
 }
 return 0;
}

————————————————亚历山大而扁扁的分割线————————————

这一周感触最深的就是能码出自己思想的代码才是最幸福的,虽然现在是在打基础,想得也是前人想过的,可能最后绞尽脑汁也想不出来,但是真的要在最初的时候自己想思路,实在不行再借鉴神牛的,万一(似乎一点信心都没)想出来了,真是要比码别人思想的代码要有成就的多啊。

~众里寻wa千百度,蓦然回首,那A却在保密最深处。

0 0