buctoj-2022寒假集训5

问题 A: 回文数

若一个数(首位不为零)从左向右读与从右向左读都一样,我们就将其称之为回文数。
  例如:给定一个10进制数56,将5665(即把56从右向左读),得到121是一个回文数。

  又如:对于10进制数87:
  STEP1:87+78  =  165  STEP2:165+561  =  726
  STEP3:726+627  =  1353  STEP4:1353+3531  =  4884

  在这里的一步是指进行了一次N进制的加法,上例最少用了4步得到回文数4884。

  写一个程序,给定一个N(2< =N< =10或N=16)进制数M(其中16进制数字为0-9与A-F),求最少经过几步可以得到回文数。
  如果在30步以内(包含30步)不可能得到回文数,则输出“Impossible!

输入格式

两行,N与M 
 N(2< =N< =10或N=16)
 M最多不超过100

输出格式

如果能在30步以内得到回文数,输出“STEP=xx”(不含引号),其中xx是步数;否则输出一行”Impossible!”(不含引号)

输入样例 复制

9 
87

输出样例 复制

STEP=6 

代码

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

int m[100]={0}; //全局变量m用于读入数据、比较
int cnt=0; //全局变量cnt用于计算次数

int palin(int m[],int len){ //判断是否是回文数组的函数
	int i,j=len-1;
	int flag=1;
	for(i=0;i<len/2;i++){
		if(m[i]!=m[j]){
			flag=0;
			break;
		}
		j--;
	}
	return flag;
}

void invert(int m[],int n,int d){ //进行n进制回文相加操作的函数
	int i,j;
	int vert[d]; //转置数组
	cnt++;
	for(i=0,j=d;i<d;i++){
		vert[i]=m[j-1];
		j--;
	} 
	for(i=0;i<d;i++){
		m[i]+=vert[i];
		if(m[i]>=n){ //模拟进位
			m[i+1]++;
			m[i]-=n;
		}
	}
	int len;
	for(i=99;i>=0;i--){
		if(m[i]!=0){
			len=i+1; //len是m有效位数的长度,等会传入函数
			break;
		}
	}
	if(palin(m,len)!=1&&cnt<=30){ //不是回文数组且cnt<=30时,继续执行invert函数
	invert(m,n,len);
	}
}

int main(){
	int n,step=0,i,len,j;
	cin>>n;
	char str[101]={0};
	scanf("%s",str);//读入str,将str拆解给m 
	for(i=0,j=strlen(str)-1;i<strlen(str);i++){
		if(n<=10)m[i]=str[j]-'0';
		else{ //16进制
			if(str[j]>='0'&&str[j]<='9'){
				m[i]=str[j]-'0';
			}else if(str[j]>='A'&&str[j]<='F'){
				m[i]=str[j]-'A'+10;
			}
		}
		j--;
	}
	for(i=99;i>=0;i--){
		if(m[i]!=0){
			len=i+1; //计算m有效位数的长度 
			break;
		}
	}
	invert(m,n,len);
	if(cnt>=31)cout<<"Impossible!";
	else cout<<"STEP="<<cnt;
	return 0;
}

问题 B: 高精度加法题目描述

输入两个大整数a和b,输出这两个整数的和。a和b都不超过100位。

输入格式

输入包括两行,第一行为一个非负整数a,第二行为一个非负整数b。两个整数都不超过100位,两数的最高位都不是0。

输出格式

输出一行,表示a + b的值。

输入样例 复制

20100122201001221234567890
2010012220100122

输出样例 复制

20100122203011233454668012
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main(){
    int a[100]={0},b[100]={0};
    char str1[101]={0},str2[101]={0};
    int i,j;
    scanf("%s",str1);
    scanf("%s",str2);
    for(i=0,j=strlen(str1)-1;i<strlen(str1);i++){
        a[i]=str1[j]-'0';
        j--;
    }
    for(i=0,j=strlen(str2)-1;i<strlen(str2);i++){
        b[i]=str2[j]-'0';
        j--;
    }
    for(i=0;i<max(strlen(str1),strlen(str2));i++){
        a[i]=a[i]+b[i];
        if(a[i]>=10){
            a[i+1]++;
            a[i]%=10;
        }
    }
    for(i=99;i>=0;i--){
        if(a[i]!=0)break;
    }
    for(;i>=0;i--){
        cout<<a[i];
    }
    return 0;
}

问题 C: 高精度减法

题目描述

输入两个大整数a和b,输出这a-b的结果。a和b都不超过100位。

输入格式

输入包括两行,第一行为一个非负整数a,第二行为一个非负整数b。两个整数都不超过100位,两数的最高位都不是0。

输出格式

输出一行,表示a - b的值。

输入样例 复制

111111111111111111111111
111111111111111111111111

输出样例 复制

0

数据范围与提示

结果可能为负数

#include<iostream>
#include<cstring> //使用c风格字符串
#include<algorithm>
using namespace std;
int main(){
	int a[100]={0},b[100]={0};
	char str1[101]={0},str2[101]={0};
	int i,j,flag=0,k=0,cnt=0;
	scanf("%s",str1); //%s可以过滤回车
	scanf("%s",str2);
	for(i=0,j=strlen(str1)-1;i<strlen(str1);i++){
		a[i]=str1[j]-'0'; //将str每位倒序存入数组
		j--;
	}
	for(i=0,j=strlen(str2)-1;i<strlen(str2);i++){
		b[i]=str2[j]-'0';
		j--;
	}

	for(i=0;i<max(strlen(str1),strlen(str2));i++){
		a[i]=a[i]-b[i]; //作减法
		if(a[i]<0){ //模拟借位
			a[i]=10+a[i];
			a[i+1]--;
		}   
	}
	for(i=99;i>=0;i--){
		if(a[i]!=0){ //找到非零的第一位
			break;
		}
	}
	if(a[i]<0){ //如果是负数
		a[i]++;
		flag=-1; 
		k--;
		for(i=i-1;i>0;i--){
			a[i]=9-a[i]; //负数的话,需要进行此运算
		}
		a[0]=10-a[0];
		for(i=0;i<strlen(str1);i++){ //但要小心还有a[0]=10的情况,如200-500
			if(a[i]==10){ //如果a[0]=10,进位,再考虑a[1]是否也需要进位,因为只有100位,没有设置break
				a[i]=0;
				a[i+1]++;
			}
		}
	}
	
	for(i=99;i>=0;i--){
		if(a[i]!=0){
			k=i; //找到现在非零的首位
			break;
		}
	}
	if(flag==-1)cout<<"-"; //如果是负数输出负号
	for(k;k>=0;k--){
		cout<<a[k];
	}
	return 0;
}

问题 E: 视频合并问题

题目描述

有多个视频需要合并为一个视频,假设一次只能将两个视频进行合并,合并需要的时间为该两个视频的时间之和。请计算将多个视频合并为一个视频需要的最小时间为多少?

输入格式

输入的第一行包含一个正整数n,表示共有n个视频需要合并。其中n不超过100。 第二行中有n个用空格隔开的正整数,分别表示n个视频的时间。

输出格式

输出包括一个正整数,即合并需要的最小时间。

输入样例 复制

8
5 29 7 8 14 23 3 11

输出样例 复制

271

代码

#include<iostream>
#include<algorithm>
using namespace std;
int main(){
	int n;
	cin>>n;
	int k=n;
	int a[n];
	int i,j=n-1;
	for(i=0;i<n;i++){
		cin>>a[i];
	}
	sort(a,a+n);
	long long sum=0;
	if(n>1){
	for(i=0;i<k-1;i++){
	a[0]+=a[1]; //合并时间最短的两个视频
	sum+=a[0];
	for(j=1;j<n-1;j++){
		a[j]=a[j+1]; //数组从2开始逐个前移一位
	}
	n--;
	sort(a,a+n); //再次排序
	}}
	cout<<sum;
	return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值