4 回文数
对于一个自然数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
Accepted
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
void rever(string a){ //可用 reverse(a.begin(), a.end());代替
int i,j;
char temp;
int len=(int)a.size()-1;
if(len%2){
for(i=0,j=len-1;i!=j;i++,j--){
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
if(len%2==0){
for(i=0,j=len-1;i!=j-1;i++,j--){
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
string sum_str(string m,int n){
int temp = 0,i;
int flag=0;
string a;
int j=(int)m.size()-1;
for(i=0;i<m.size()&&j>=0;i++,j--){
temp=0;
if(m[i]>='0'&&m[i]<='9') temp+=(m[i]-'0');
if(m[j]>='0'&&m[j]<='9') temp+=(m[j]-'0');
if(m[i]>='A'&&m[i]<='Z')temp+=(m[i]-'A')+10;
if(m[j]>='A'&&m[j]<='Z')temp+=(m[j]-'A')+10;
if(flag==1){//进位1
temp++;
flag=0;
}
if(temp>=n){//大于n要进位
flag=1;
temp-=n;}
if(temp<10) temp+='0';
else temp=temp-10+'A';
a+=temp;
}
if(flag==1){
a=a+"1";
}
rever(a);
return a;
}
int judge(string m){
int i,j;
for(i=0,j=(int)m.size()-1;i<m.size()&&j>=0;i++,j--){
if(m[i]!=m[j]) return 0;
}
return 1;
}
int main() {
int n;
int step=0;
string m;
cin >> n;
cin >> m;
if(judge(m)) cout << "STEP=" <<step << endl;
else{
while(step<=30){
m=sum_str(m,n);
step++;
if(judge(m)){
cout << "STEP=" <<step << endl;
break;
}
}
}
if(step>30) {cout << "NO" << endl; }
return 0;
}
高精度计算加减乘除
5 数楼梯
楼梯有N阶,上楼可以一步上一阶,也可以一步上两阶。那么走到第N阶楼梯共有多少种不同的走法呢?
输入格式
一个正整数 N(1<=N<=5000),表示楼梯阶数。
输出格式
输出一个数,表示走到第N阶楼梯有多少种走法。
注意,数据范围很大,即使是64位也可能不够存。
输入样例1
4
输出样例1
5
输入样例2
400
输出样例2
28481229810848961175798893768146099561538008878230489098647719564596927140403
Accepted
(来源:洛谷)
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
int len=1,fl[5005][5005]={0};//fl[k][i]--第k阶台阶所对应的走法数
void floor(int k){
int i;
for(i=1;i<=len;i++)
fl[k][i]=fl[k-1][i]+fl[k-2][i];
for(i=1;i<=len;i++){
if(fl[k][i]>=10){
fl[k][i+1]+=fl[k][i]/10;
fl[k][i]=fl[k][i]%10;
if(fl[k][len+1]) len++;
}
}
}
int main() {
int n;
cin >> n;
fl[1][1]=1;
fl[2][1]=2;
for(int i=3;i<=n;i++){
floor(i);
}
for(int i=len;i>=1;i--){
printf("%d",fl[n][i]);
}
return 0;
}
这道题我们可以论述一下递推与递归的方法与区别
递推一般用循环来解决,从已知条件到未知逐渐接近结果:
(1)将复杂运算分解为若干重复的简单运算
(2)后一步骤建立在前一步骤之上
(3)计算每一步骤的方法相同
(4)从开始向后计算出结果
(5)使用循环结构,通过多次循环逐渐逼近结果
递归一般自己调用自己,从未知到已知,把规模大的、较难解决的问题变成规模较小的、易解决的同一问题。规模较小的问题又变成规模更小的问题,并且小到一定程度可以直接得出它的解,从而得到原来问题的解。
(1)每一次递归都缩小问题规模,直到问题足够小
(2)使用选择分支语句
(3)从后往开始逐步逼近
(4)达到最开始,再把初始值带入往后逐一求解
6 A-B
已知两个数A和B,求A-B的运算结果。
输入格式
输入包括两个正整数A和B 。(0<A,B≤1e10086)
输出格式
输出A-B的运算结果。
输入样例1
3
2
输出样例1
在这里给出相应的输出。例如:
1
输入样例2
11102356985410
2356985410235698
输出样例2
在这里给出相应的输出。例如:
-2345883053250288
Wrong Answer
给出我的比较麻烦的代码(只有90分,待修改)
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
int sign=0;
string sub(string a,string b){
string ans;
int temp;
long long lena=(int)a.size();
long long lenb=(int)b.size();
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
long long i;
int flag=0;
if(lena<lenb){
sign=1;
for(i=0;i<lenb;i++){
int at=0,bt=0;
if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
temp=bt-at;
if(flag==1) {
temp--;
flag=0;
}
if(temp<0){
temp+=10;
flag=1;
}
ans+=temp+'0';
}
// if(temp<0) sign=1;
}
if(lena==lenb){
if(a<b) sign=1;
if(sign){
for(i=0;i<lenb;i++){
int at=0,bt=0;
if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
temp=bt-at;
if(flag==1) {
temp--;
flag=0;
}
if(temp<0){
temp+=10;
flag=1;
}
ans+=temp+'0';
}
// if(temp<0) sign=1;
}
else{
for(i=0;i<lena;i++){
int at=0,bt=0;
if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
temp=at-bt;
if(flag==1) {
temp--;
flag=0;
}
if(temp<0){
temp+=10;
flag=1;
}
ans+=temp+'0';
}
//if(temp<0) sign=1;
}
}
if(lena>lenb){
for(i=0;i<lena;i++){
int at=0,bt=0;
if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
temp=at-bt;
if(flag==1) {
temp--;
flag=0;
}
if(temp<0){
temp+=10;
flag=1;
}
ans+=temp+'0';
}
// if(temp<0) sign=1;
}
reverse(ans.begin(), ans.end());
return ans;
}
int main() {
string a,b;
string ans;
int flag=0;
cin >> a;
getchar();
cin >> b;
getchar();
if(a==b) {
cout << "0" << endl;
return 0;
}
ans=sub(a,b);
if(sign) cout <<"-";
for(long long i=0;i<ans.size();i++){
if(flag==0&&ans[i]!='0'){
cout << ans[i];
flag=1;
}
else if(flag==1){
cout << ans[i];
}
}
return 0;
}
后来询问发现,第一版错的原因在于当两个数长度不相等时,未对数字进行相应的初始化。
更改后终于AC:
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
int sign=0;
string sub(string a,string b){
string ans;
int lena=(int)a.size();
int lenb=(int)b.size();
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
int i;
int flag=0;
if(lena<lenb){
sign=1;
for(i=lena;i<lenb;i++){
a+=' ';
}
for(i=0;i<lenb;i++){
int at=0,bt=0;
if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
int temp=bt-at;
if(flag==1) {
temp--;
flag=0;
}
if(temp<0){
temp+=10;
flag=1;
}
ans+=temp+'0';
}
}
if(lena==lenb){
if(a<b) sign=1;
if(sign){
for(i=0;i<lenb;i++){
int at=0,bt=0;
if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
int temp=bt-at;
if(flag==1) {
temp--;
flag=0;
}
if(temp<0){
temp+=10;
flag=1;
}
ans+=temp+'0';
}}
else{
for(i=0;i<lena;i++){
int at=0,bt=0;
if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
int temp=at-bt;
if(flag==1) {
temp--;
flag=0;
}
if(temp<0){
temp+=10;
flag=1;
}
ans+=temp+'0';
}
}
}
if(lena>lenb){
for(i=lenb;i<lena;i++){
b+=' ';
}
for(i=0;i<lena;i++){
int at=0,bt=0;
if(a[i]>='0'&&a[i]<='9') at=a[i]-'0';
if(b[i]>='0'&&b[i]<='9') bt=b[i]-'0';
int temp=at-bt;
if(flag==1) {
temp--;
flag=0;
}
if(temp<0){
temp+=10;
flag=1;
}
ans+=temp+'0';
}
}
reverse(ans.begin(), ans.end());
return ans;
}
int main() {
string a={0},b={0};
string ans;
int flag=0;
cin >> a;
getchar();
cin >> b;
// getchar();
if(a==b) {
cout << "0" << endl;
return 0;
}
ans=sub(a,b);
if(sign) cout <<"-";
for(int i=0;i<ans.size();i++){
if(flag==0&&ans[i]!='0'){
cout << ans[i];
flag=1;
}
else if(flag==1){
cout << ans[i];
}
}
return 0;
}
Accepted
(来源:大数减法)
第二版更加简练,把判断的部分放在main函数中,且AC了
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string.h>
using namespace std;
string sub(string a,string b,int len){
int i;
string ans;
int lenb=(int)b.size();
for(i=0;i<lenb;i++){
if(a[i]>=b[i]){ //不需要向前借1
ans+=a[i]-b[i]+'0';
}
else{//需要向前借1
ans+=a[i]+10-b[i]+'0';
a[i+1]--;
}
}
for(;i<len;i++){
ans+=a[i];
}
reverse(ans.begin(), ans.end());
return ans;
}
int main() {
string a,b;
string ans;
int i;
int flag=0;
cin >> a >> b;
reverse(a.begin(), a.end());
reverse(b.begin(), b.end());
int lena=(int)a.size();
int lenb=(int)b.size();
if(lena>lenb){ ////若减数长度 > 被减数长度,正常减
ans=sub(a,b,lena);
for(i=0;i<ans.size();i++){
if(flag==0&&ans[i]>'0'&&ans[i]<='9') {
cout << ans[i];
flag=1;
}
else if(flag==1) cout << ans[i];
}
return 0;
}
else if(lena<lenb){//若减数长度 < 被减数长度,被减数-减数
cout <<"-";
ans=sub(b,a,lenb);
for(i=0;i<ans.size();i++){
if(flag==0&&ans[i]>'0'&&ans[i]<='9') {
cout << ans[i];
flag=1;
}
else if(flag==1) cout << ans[i];
}
return 0;
}
else{//若减数长度 == 被减数,判断两个数的大小
if(a>b){
ans=sub(a,b,lena);
for(i=0;i<ans.size();i++){
if(flag==0&&ans[i]>'0'&&ans[i]<='9') {
cout << ans[i];
flag=1;
}
else if(flag==1) cout << ans[i];
}
}
else if(a<b){
cout <<"-";
ans=sub(b,a,lenb);
for(i=0;i<ans.size();i++){
if(flag==0&&ans[i]>'0'&&ans[i]<='9') {
cout << ans[i];
flag=1;
}
else if(flag==1) cout << ans[i];
}
}
else{
cout << "0" << endl;
}
}
return 0;
}
7 高精度除法
给两个正整数 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
Accepted
(来源:大数除法)
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int L=11000;
int sub(int *a,int *b,int lena,int lenb)
{
if(lena<lenb) return -1;//如果a小于b,则返回-1
if(lena==lenb)
{
for(int i=lena-1;i>=0;i--)
if(a[i]>b[i]) break;
else if(a[i]<b[i]) return -1;//如果a小于b,则返回-1
}
for(int i=0;i<lena;i++)//高精度减法
{
a[i]-=b[i];
if(a[i]<0) {a[i]+=10;a[i+1]--;}
}
for(int i=lena-1;i>=0;i--)
if(a[i]) return i+1;//返回差的位数
return 0;//返回差的位数
}
string div(string n1,string n2)//n1,n2是字符串表示的被除数
{
string s,v;//s存商,v存余数
int a[L]={0},b[L]={0},r[L]={0},lena=n1.size(),lenb=n2.size(),i;//a,b是整形数组表示被除数,除数
for(i=lena-1;i>=0;i--) a[lena-1-i]=n1[i]-'0';
for(i=lenb-1;i>=0;i--) b[lenb-1-i]=n2[i]-'0';
if(lena<lenb || (lena==lenb && n1<n2)) {
return "0";
}//如果a<b,则商为0
int t=lena-lenb;//除被数和除数的位数之差
for(int i=lena-1;i>=0;i--)//将除数扩大10^t倍
if(i>=t) b[i]=b[i-t];
else b[i]=0;
lenb=lena;
for(int j=0;j<=t;j++)
{
int temp;
while((temp=sub(a,b+j,lena,lenb-j))>=0)//如果被除数比除数大继续减
{
lena=temp;
r[t-j]++;
}
}
for(i=0;i<L-10;i++) {r[i+1]+=r[i]/10;r[i]%=10;}//统一处理进位 ??
while(!r[i]) i--;//将整形数组表示的商转化成字符串表示的
while(i>=0) s+=r[i--]+'0';
return s;
}
int main()
{
string a,b;
cin>>a>>b;
cout<<div(a,b)<<endl;
return 0;
}