回文数

对于一个自然数n,若将n的各位数字反向排列所得的数n1与n相等,则称n为回文数,例如2332。

若给定一个N( 2<=N<=16)进制数M(M的长度在一百位以内),如果M不是回文数,可以对其进行N进制加法,最终得到回文数。

例如对于十进制数79 STEP1 : 79 + 97 = 176 STEP2 : 176 + 671 = 847 STEP3 : 847 + 748 = 1595 STEP4 : 1595 +5951 = 7546 STEP5 : 7546 + 6457 = 14003 STEP6 : 14003 + 30041 = 44044

那么对于给定的N进制数M,请判断其能否在30步以内(包括30步)得到回文数。

输入格式:

第一行包括一个正整数 N(2<=N<=16)。

第二行包括一个正整数M(一百位以内)。

输出格式:

如果可以在n步内得到回文数,输出“STEP=n”,否则输出“NO”。

输入样例1:
10
79
输出样例1:
STEP=6
输入样例2:
8
665556
输出样例2:
NO

这题不算难,但就是有好多小细节会让我在解题过程中遇到挫折。对于这题我自己写了比较多的函数,解法也是比较暴力。

思路:首先因为数字可能会超过64位,这样的数字太大,于是我用了字符数组来储存数字,再用另一个字符数组来储存原字符数组的颠倒数。相加的话就是像小学加法一样,只不过这个是要根据不同的进制规则来进位,比如八进制,当两数相加为8就要往前进一位。而根据我编写的函数就有进制相加还有数字转换的函数。

这次的代码较多的都是一些解决问题的函数,我就不附上主函数代码了,赋上一些更重要的小函数代码。

void tran_number(char a[],char b[],int c)//将字符型数字转换为其ASCII值较好计算的值
{
int i;
for(i=0;i<c;i++)
{
if(a[i]>=48&&a[i]<58)a[i]-=48;
else if(a[i]>=65&&a[i]<91) a[i]-=55;
else if(a[i]>=97&&a[i]<123) a[i]-=87;
if(b[i]>=48&&b[i]<58)b[i]-=48;
else if(b[i]>=65&&b[i]<91) b[i]-=55;
else if(b[i]>=97&&b[i]<123) b[i]-=87;
}
}
char tran_number2(char a)//这是避免遇到0是,strlen这个函数会认为这个字符已结束
{
if(a>=0&&a<9)a+=48;
else if(a>=10&&a<17) a+=55;
return a;
}
void tran(char a[],char b[],int c,int d)
{
void tran_number(char a[],char b[],int c);
char tran_number2(char a);
int i;
tran_number(a,b,d);
for(i=0;i<d;i++)
{ if(c==11){
a[i]=a[i]+b[i];
if(a[i]==10)a[i]='A';
if(a[i]>=11&&a[i]!='A'){
a[i]=a[i]%11;
a[i+1]+=1;
if(i+1==d) a[i+1]=tran_number2(a[i+1]);
}
a[i]=tran_number2(a[i]);
}
else if(c==12){
a[i]=a[i]+b[i];
if(a[i]==10)a[i]='A';
else if(a[i]==11)a[i]='B';
if(a[i]>=12&&a[i]!='A'&&a[i]!='B'){//一开始有三个点没过就是卡在了这个if判断的地方,当我在if判断之前将值未大于12的值赋上了字符A或B,这将会导致其ASCII值大于12,从而影响判断
a[i]=a[i]%12;
a[i+1]+=1;
if(i+1==d) a[i+1]=tran_number2(a[i+1]);
}
a[i]=tran_number2(a[i]);
}
else if(c==13){
a[i]=a[i]+b[i];
if(a[i]==10)a[i]='A';
else if(a[i]==11)a[i]='B';
else if(a[i]==12)a[i]='C';
if(a[i]>=13&&a[i]!='A'&&a[i]!='B'&&a[i]!='C'){
a[i]=a[i]%13;
a[i+1]+=1;
if(i+1==d) a[i+1]=tran_number2(a[i+1]);
}
a[i]=tran_number2(a[i]);
}
else if(c==14){
a[i]=a[i]+b[i];
if(a[i]==10)a[i]='A';
else if(a[i]==11)a[i]='B';
else if(a[i]==12)a[i]='C';
else if(a[i]==13)a[i]='D';
if(a[i]>=14&&a[i]!='A'&&a[i]!='B'&&a[i]!='C'&&a[i]!='D'){
a[i]=a[i]%14;
a[i+1]+=1;
if(i+1==d) a[i+1]=tran_number2(a[i+1]);
}
a[i]=tran_number2(a[i]);
}
else if(c==15){
a[i]=a[i]+b[i];
if(a[i]==10)a[i]='A';
else if(a[i]==11)a[i]='B';
else if(a[i]==12)a[i]='C';
else if(a[i]==13)a[i]='D';
else if(a[i]==14)a[i]='E';
if(a[i]>=15&&a[i]!='A'&&a[i]!='B'&&a[i]!='C'&&a[i]!='D'&&a[i]!='E'){
a[i]=a[i]%15;
a[i+1]+=1;
if(i+1==d) a[i+1]=tran_number2(a[i+1]);
}
a[i]=tran_number2(a[i]);
}
else if(c==16){
a[i]=a[i]+b[i];
if(a[i]==10)a[i]='A';
else if(a[i]==11)a[i]='B';
else if(a[i]==12)a[i]='C';
else if(a[i]==13)a[i]='D';
else if(a[i]==14)a[i]='E';
else if(a[i]==15)a[i]='F';
if(a[i]>=16&&a[i]!='A'&&a[i]!='B'&&a[i]!='C'&&a[i]!='D'&&a[i]!='E'&&a[i]!='F'){
a[i]=a[i]%16;
a[i+1]+=1;
if(i+1==d) a[i+1]=tran_number2(a[i+1]);
}
a[i]=tran_number2(a[i]);
}
else{
a[i]=a[i]+b[i];
if(a[i]>=c){
a[i]=a[i]%c;
a[i+1]+=1;
if(i+1==d) a[i+1]=tran_number2(a[i+1]);
}
a[i]=tran_number2(a[i]);
}
}
}
int judge(char a[])//判断该字符数组是否回文的函数
{
int n,i,j,y=0;
n=strlen(a);
for(i=0,j=n-1;i<=j;i++,j--)
{
if(a[i]==a[j])y++;
}
if(n%2==0){
if(y==n/2)return 1;
else return 0;
}
else{
if(y==(n+1)/2)return 1;
else return 0;
}
}

A-B

已知两个数A和B,求A-B的运算结果。

输入格式:

输入包括两个正整数A和B 。(0<A,B≤1e10086)

输出格式:

输出A-B的运算结果。

输入样例1:
3
2 输出样例1:
1
输入样例2:
11102356985410
2356985410235698 输出样例2:
-2345883053250288

思路:由于可能输入的数字会很大,long long int可能也储存不了,于是我用了字符串来储存数字。运用数学减法规则来编写函数(向前借位的思想)。解法十分暴力,容易理解。

赋上主要的函数:

//将每个字符的ASCII值转化为10以内的数字
void tran1(char a[],int n)
{
int i; for(i=0;i<n;i++)
{
a[i]-=48;
}
}

其实写到后面感觉这步可以省去,但是由于前面很多东西需要改(因为懒),我就保留了这个函数

//将每位字符的ASCII值转化为可以输出数字字符的值
void tran2(char a[],int n)
{
int i;
for(i=0;i<n;i++)
{
a[i]+=48;
}
}

之所以再转换成这个函数,一是为了方便输出,二是如果遇到相减值为0的数字,会被认为字符到这停止,就不会再输出后面的字符了。

void cul(char a[],int n,char b[],int m)
{
int i,j,r,c,d;
tran1(a,n);
tran1(b,m);
c=n-1;
d=m-1;
while(d>=0){
if(a[c]-b[d]<0){//判断两数相减是否小于零,若小于零则要开始向前借位
if(a[c-1]-1<0){
r=c-1;
while(a[r]-1<0){
a[r]-=1;
a[r]+=10; r--;
}
a[r]-=1;
}
else a[c-1]-=1;
a[c]+=10;
a[c]=a[c]-b[d];//一开始因为这个地方只有...啊,忘记几分了。这个地方主要解决的问题是如果向前借一位后前面的那个数字也小于0,就要再向前借 }
else a[c]=a[c]-b[d];
c--;
d--;
}
for(i=0;i<n;i++)
{
if(a[i]!=0)break;
}
j=i;
for(i=j,r=0;r<n-j;i++,r++)
{
a[r]=a[i];//若前面的字符值为0,就要将字符数组向前移
}
a[n-j]='\0';//最后修改了这个地方才AC,主要是因为我测了一组10-9的数据,出来的答案后面总会带个方框,想必是将数组前移的过程中原本的字符的ACSII码还是1导致的
tran2(a,n-j); }

主函数如下

#include<stdio.h>
#include<string.h>
char x[10000],y[10000];
void tran1(char a[],int n);
void tran2(char a[],int n);
void cul(char a[],int n,char b[],int m);
int main()
{
scanf("%s %s",x,y);
int x1,y1;
x1=strlen(x);
y1=strlen(y);
if(x1==y1){
if(strcmp(x,y)>0){
cul(x,x1,y,y1);
printf("%s",x);
return 0;
}//第一个数大于第二个数
else if(strcmp(x,y)==0){
printf("0");
return 0;
}
else{
cul(y,y1,x,x1);
printf("-%s",y);
return 0;
}//第一个数小于第二个数
}
else if(x1>y1){
cul(x,x1,y,y1);
printf("%s",x);
return 0;
}//第一个数大于第二个数
else{
cul(y,y1,x,x1);
printf("-%s",y);
return 0;
} //第二个数大于第一个数 }

附上一个干货大数加减乘除

高精度除法

给两个正整数 a,b,求 a/b的整数部分。

输入格式:

输入共两行,每行一个正整数,分别表示 a和b。 50%数据,a,b均小于1e18, 50%数据,a,b均小于1e500。

输出格式:

输出一个整数,表示a/b的整数部分。

输入样例1:
3
2
输出样例1:
1
输入样例
24781236498237462378425347823652387423654238752372365327862
8934457724628746
输出样例2:
2773669903874014740488146558678531750078864

主要思路其实大家都知道,就是把除法通过减法来实现,再进行一些将较小的数扩大整百倍的处理,使这种方法可以不那么暴力,主要是想要记录一些自己做题过程中遇到的问题。

1.用新开数组来储存结果,这里碰到数字为0的时候会被认为是字符数组结束了,这时要将0转换为ASCII为48的值,那就要对于这个数组有位数的判断了,这时我采取了分情况讨论。

2.测试100/1时会出现“方框00”,这就是对于新开数组的位数判断错误而造成的错误答案。

这次就只附上最核心的代码了

void tran1(char a[],int n);//转换ASCII码值:大转小
void tran2(char a[],int n);//转换ASCII码值,小转大
void sub(char a[],int n,char b[],int m);//大数相减
void chu(char a[],int n,char b[],int m);//大数相除
void chu(char a[],int n,char b[],int m)
{
int t=0,i,flag=0,n1;//flag就是为了判断新开数组的位数
n1=n;//n一直在变化,为了用到最初的n,这里新设了一个n1
while((n>m)||(n==m&&strcmp(a,b)>0)){
if(n==m){
while(strlen(a)==strlen(b)&&strcmp(a,b)>=0){
sub(a,n,b,m);
c[t]+=1;
for(t=0;c[t]==10;t++)
{
c[t]=0;
c[t+1]+=1;
}
t=0;
tran2(b,m);
} }
else{
if(a[0]>b[0]){
if(flag==0)flag=1;
for(i=m;i<n;i++)
{
b[i]+=48;
}
sub(a,n,b,n);
c[n-m]+=1;
for(t=n-m;c[t]==10;t++)
{
c[t]=0;
c[t+1]+=1;
}
t=n-m; tran2(b,m);
}
else{
if(flag==0&&a[0]!=b[0])flag=2;
else if(flag==0&&a[0]==b[0]) flag=3;
for(i=m;i<n-1;i++)
{
b[i]+=48;
}
sub(a,n,b,n-1);
c[n-m-1]+=1;
for(t=n-m-1;c[t]==10;t++)
{
c[t]=0;
c[t+1]+=1;
}
t=n-m-1; tran2(b,m);
}
}n=strlen(a);
}
if(flag==0){
for(t=0;c[t]==0;)
{
t++;
}
for(;c[t]!=0;)
{
t++;
}
}
else if(flag==1||flag==3)t=n1-m+1;
else t=n1-m;
tran2(c,t); }

数楼梯

楼梯有N阶,上楼可以一步上一阶,也可以一步上两阶。那么走到第N阶楼梯共有多少种不同的走法呢?

输入格式:

一个正整数 N(1<=N<=5000),表示楼梯阶数。

输出格式:

输出一个数,表示走到第N阶楼梯有多少种走法。

注意,数据范围很大,即使是64位也可能不够存。

输入样例1:
4
输出样例1:
5
输入样例2:
400
输出样例2:
284812298108489611757988937681460995615380088782304890986477195645969271404032323901

这是数据可能会非常大的斐波那契数列,看到一个斐波那契数列的四种实现方式(C语言),但是对我好像没有什么屁用。找到解决问题的突破口是将前几个数列出来了,找到了规律。其实这个和兔子数差不多,虽然也没什么屁用,但我就是想讲,因为现在心情很烦躁,md

os:有什么不良词汇我会酌情码出,也请你们假装没看到的亚子。

规律:N=1,f=1;N=2,f=2;N=3,f=3;N=4,f=5;N=5,f=6;

这次败在对于数组的基础不扎实,心烦意乱,心气浮躁。

但也还算有收获,不然我真的会在本篇博客不停地口吐芬芳,对,忽略这些。改变了自己大数运算的方法,其实换了一张皮还是没有改变根本,是把字符串换成了int类型的数组,一个数组元素就存一个0-9内的数,然后逆序输出。

关于本次写的加法代码如下:

for(j=0;b[j]!=-1;j++)
{
if(a[j]!=-1)b[j]+=a[j];
}
for(j=0,r=0;b[j]!=-1;j++,r++)
{
if(b[j]>9){
x=b[j];
b[j]=x%10;
if(b[j+1]==-1)b[j+1]=1;
else{
b[j+1]+=x/10; }
}
}

赋上完整代码了:

#include<stdio.h>

int main()
{ int a[10000],b[10000],c[10000];
int N,r,j,i,x;
a[0]=1;
b[0]=2;
for(i=1;i<10000;i++)
{
a[i]=-1;
b[i]=-1;
c[i]=-1;
}
scanf("%d",&N);
if(N==0)printf("0");
else if(N==1)printf("1");
else if(N==2)printf("2"); else{ for(i=0;i<N-2;i++)
{
for(j=0;b[j]!=-1;j++)
{
c[j]=b[j];
}
for(j=0;b[j]!=-1;j++)
{
if(a[j]!=-1)b[j]+=a[j];
}
for(j=0,r=0;b[j]!=-1;j++,r++)
{
if(b[j]>9){
x=b[j];
b[j]=x%10;
if(b[j+1]==-1)b[j+1]=1;
else{
b[j+1]+=x/10; }
}
}
for(j=0;c[j]!=-1;j++)
{
a[j]=c[j];
}
}
for(i=r-1;i>=0;i--)
{
printf("%d",b[i]);
}
}
return 0;
}

这次做题过程中学到了memset,但测试了一下怎么比for的循环赋值耗费的时间还长,差不多6ms。赋上干货C语言数组初始化的三种常用方法,填补了我知识的漏洞。

有一个很大的心得:看了别人的很多题解,其实具体做法完全没有理解,只掌握了一个大概思路,在自己能力还没那么高的前提下,我觉得还是先用自己的思维把题给解出来,这样才是自己完全地理解性地做题目,其实我心知肚明自己的方法笨得要死,但是达到目的不就行啦哈哈,更巧妙地题解可能在自己学习和能力提高的过程中再慢慢理解了。

第三周PTA笔记 回文数+A-B(大数减法)+高精度除法+数楼梯(大数加法)的更多相关文章

  1. 《Linux内核分析》第三周学习笔记

    <Linux内核分析>第三周学习笔记 构造一个简单的Linux系统MenuOS 郭垚 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.stud ...

  2. Linux内核分析第三周学习笔记

    linux内核分析第三周学习笔记 标签(空格分隔): 20135328陈都 陈都 原创作品转载请注明出处 <Linux内核分析>MOOC课程http://mooc.study.163.co ...

  3. LINUX内核设计与实现第三周读书笔记

    LINUX内核设计与实现第三周读书笔记 第一章 LINUX内核简介 1.1 Unix的历史 1969年的夏天,贝尔实验室的程序员们在一台PDR-7型机上实现了Unix这个全新的操作系统. 1973年, ...

  4. 练习三十:Python回文数判断编程练习。

    说到回文数,大家可能会比较的陌生,但是在我们的日常生活中常会遇到这样的数字,只是你不知道它是回文数罢了. 例如:12321,这组数字就是回文数. 设n是一任意自然数.若将n的各位数字反向排列所得自然数 ...

  5. hiho一下 第一周 最长回文子串

    时间限制:1000ms 单点时限:1000ms 内存限制:64MB 描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这 ...

  6. Linux内核分析——第三周学习笔记20135308

    第三周 构造一个简单的Linux系统MenuOS 计算机三个法宝: 1.存储程序计算机 2.函数调用堆栈 3.中断 操作系统两把宝剑: 1.中断上下文的切换:保存现场和恢复现场 2.进程上下文的切换 ...

  7. 【hiho一下】第一周 最长回文子串

    题目1:最长回文子串 题目原文:http://hihocoder.com/contest/hiho1/problem/1 [题目解读] 题目与 POJ 3974 palindrome 基本同样.求解最 ...

  8. hiho一下第一周 最长回文子串

    题目链接:http://hihocoder.com/contest/hiho1/problem/1 #include <iostream> #include <cstdio> ...

  9. hiho 第1周 最长回文子串

    题目链接:http://hihocoder.com/problemset/problem/1032 #include <bits/stdc++.h> using namespace std ...

随机推荐

  1. 讲师征集| .NET Conf China 2021正式启动

    最近社区小伙伴们一直在为11月即将在武汉举办的 第三届.NET中国峰会而忙碌,社区活动官网设计和开发工作还在进行,我们在国庆节的前一天晚上向社区正式启动了活动的序幕,也就是我们确定好了举办地点.时间, ...

  2. uniapp小程序迁移到TS

    uniapp小程序迁移到TS 我一直在做的小程序就是 山科小站 也已经做了两年了,目前是用uniapp构建的,在这期间也重构好几次了,这次在鹅厂实习感觉受益良多,这又得来一次很大的重构,虽然小程序功能 ...

  3. AT3950 [AGC022E] Median Replace

    题目传送门 Description 有一个长度为 \(n\) 的 \(01\) 串,里面有一些还没有确定,我们标记为 ? .可以进行若干次操作,每次操作可以把三个相邻的数替换成它们的中位数.问有多少种 ...

  4. 利用ps在光污染地图上寻找最近的观星地区

    城市灯光对于天文观测和天文摄影是有害的,进行这两类活动之前应提前规划地点,下面是笔者尝试的一种利用ps在光污染地图上进行规划的方法. 目前大部分的光污染地图都是基于WA 2015绘制的,可以结合VII ...

  5. Hash窃取与传递

    Hash窃取与传递 NTHASH(NTLM) 在 Windows中, 存储的密码Hash就叫做 NTHash,也叫做 NTLM,其中NTLM 全称是 "NT LAN Manager" ...

  6. 返回值优化 RVO

    <深度探索C++对象模型>-- 2.3 返回值的初始化 & 在编译器层面做优化

  7. xpath helper插件安装提示程序包无效

    参考链接:https://www.jianshu.com/p/b7d782ef81e0 刚学到爬虫,需要在Chrome浏览器安装xpath helper插件结果一直提示"程序包无效" ...

  8. Java:AQS 小记-1(概述)

    Java:AQS 小记-1(概述) 概述 全称是 Abstract Queued Synchronizer(抽象队列同步器),是阻塞式锁和相关的同步器工具的框架,这个类在 java.util.conc ...

  9. MySQL:补充知识

    MySQL补充知识 在学习完 MySQL 基础与提高内容后: 基础知识笔记: MySQL:基础语法-1 MySQL:基础语法-2 MySQL:基础语法-3 MySQL:基础语法-4 提高知识笔记: M ...

  10. Linux服务器装Anaconda&TensorFlow

    远程Linux服务器装Anaconda&指定版本TensorFlow 说明: 由于疫情影响,原先使用的服务器已断电,故重选了一台服务器对环境重选进行搭建,正好补上这篇博文. 01 下载Anac ...