基础编程练习(六)

7-51 BCD解密 (10point(s))
BCD数是用一个字节来表达两位十进制的数,每四个比特表示一位。所以如果一个BCD数的十六进制是0x12,它表达的就是十进制的12。但是小明没学过BCD,把所有的BCD数都当作二进制数转换成十进制输出了。于是BCD的0x12被输出成了十进制的18了!

现在,你的程序要读入这个错误的十进制数,然后输出正确的十进制数。提示:你可以把18转换回0x12,然后再转换回12。

输入格式:
输入在一行中给出一个[0, 153]范围内的正整数,保证能转换回有效的BCD数,也就是说这个整数转换成十六进制时不会出现A-F的数字。

输出格式:
输出对应的十进制数。

#include<vector>
#include<iomanip>
#include<algorithm>
#include<iostream>
using namespace std;

int main()
{
	int a;
	cin>>a;
	cout<<(a/16 * 10 + a%16);
} 

7-52 求特殊方程的正整数解 (15point(s))
本题要求对任意给定的正整数N,求方程X
​2
​​ +Y
​2
​​ =N的全部正整数解。

输入格式:
输入在一行中给出正整数N(≤10000)。

输出格式:
输出方程X
​2
​​ +Y
​2
​​ =N的全部正整数解,其中X≤Y。每组解占1行,两数字间以1空格分隔,按X的递增顺序输出。如果没有解,则输出No Solution。

#include<vector>
#include<iomanip>
#include<algorithm>
#include<iostream>
using namespace std;

int main()
{
	int N;
	cin>>N;
	int key = 0;
	for(int i = 1; i < N/2;  i ++)
	{
		for(int j = i + 1; j < N/2; j ++)
		{
			if(i*i + j*j == N)
			{
				cout<<i<<" "<<j<<endl;
				key = 1;
			}
		}
	}
	if(!key)
	{
		cout<<"No Solution";
	}
} 

7-53 掉入陷阱的数字 (15point(s))
对任意一个自然数N
​0
​​ ,先将其各位数字相加求和,再将其和乘以3后加上1,变成一个新自然数N
​1
​​ ;然后对N
​1
​​ 重复这种操作,可以产生新自然数N
​2
​​ ;……多次重复这种操作,运算结果最终会得到一个固定不变的数N
​k
​​ ,就像掉入一个数字“陷阱”。

本题要求对输入的自然数,给出其掉入“陷阱”的过程。

输入格式:
在一行内给出一个自然数N
​0
​​ (N
​0
​​ <30000)。

输出格式:
对于输入的N
​0
​​ ,逐行输出其掉入陷阱的步骤。第i行描述N掉入陷阱的第i步,格式为: i:N
​i
​​ (i≥1)。当某一步得到的自然数结果N
​k
​​ (k≥1)与上一步N
​k−1
​​ 相同时,停止输出。

#include<vector>
#include<iomanip>
#include<algorithm>
#include<iostream>
using namespace std;
int get_num(int a);
int main()
{
	int n;
	cin>>n;
	for(int i = 1; ;i ++)
	{
		int x = get_num(n);
		if(x != n)
		{
			cout<<i<<":"<<x<<endl;
			n = x;

		}else{
			cout<<i<<":"<<x<<endl;
			break;
		}

	}
} 

int get_num(int a)
{
	int sum = 0;
	while(a)
	{
		sum += a % 10;
		a /= 10;
	}
	sum *= 3;
	sum += 1;
	return sum;
}

7-54 正整数A+B (15point(s))
题的目标很简单,就是求两个正整数A和B的和,其中A和B都在区间[1,1000]。稍微有点麻烦的是,输入并不保证是两个正整数。

输入格式:
输入在一行给出A和B,其间以空格分开。问题是A和B不一定是满足要求的正整数,有时候可能是超出范围的数字、负数、带小数点的实数、甚至是一堆乱码。

注意:我们把输入中出现的第1个空格认为是A和B的分隔。题目保证至少存在一个空格,并且B不是一个空字符串。

输出格式:
如果输入的确是两个正整数,则按格式A + B = 和输出。如果某个输入不合要求,则在相应位置输出?,显然此时和也是?。

#include<vector>
#include<iomanip>
#include<algorithm>
#include<iostream>
using namespace std;
int get_num(int a);
int main()
{
	string str1, str2;
	cin>>str1;
	getline(cin, str2);
	int key1 = 0, key2 = 0;
	int sum1 = 0, sum2 = 0;
	for(int i = 0; i < str1.length(); i ++)
	{
		if(str1[i] >= '0' && str1[i] <= '9')
		{
			sum1 *= 10;
			sum1 += str1[i] - '0';
		}else{
			key1 = 1;
			break;
		}
	}
	for(int i = 1; i < str2.length(); i ++)
	{
		if(str2[i] >= '0' && str2[i] <= '9')
		{
			sum2 *= 10;
			sum2 += str2[i] - '0';
		}else{
			key2 = 1;
			break;
		}
	}
	if(key1)
	{
		cout<<"?"<<" + ";
	}else{
		if(sum1<=1000 &&sum1>=1)
		{
			cout<<sum1<<" + ";
		}else{
			key1 = 1;
			cout<<"?"<<" + ";
		}
	}
	if(key2)
	{
		cout<<"?"<<" = ";
	}else{
		if(sum2 <= 1000 && sum2 >=1)
		{
			cout<<sum2<<" = ";
		}else{
			key2 = 1;
			cout<<"?"<<" = ";
		}
	}
	
	if(!key1 && !key2)
	{
		cout<<sum1 + sum2;
	}else{
		cout<<"?";
	}
} 


7-55 查验身份证 (15point(s))
一个合法的身份证号码由17位地区、日期编号和顺序编号加1位校验码组成。校验码的计算规则如下:

首先对前17位数字加权求和,权重分配为:{7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2};然后将计算的和对11取模得到值Z;最后按照以下关系对应Z值与校验码M的值:

Z:0 1 2 3 4 5 6 7 8 9 10
M:1 0 X 9 8 7 6 5 4 3 2
现在给定一些身份证号码,请你验证校验码的有效性,并输出有问题的号码。

输入格式:
输入第一行给出正整数N(≤100)是输入的身份证号码的个数。随后N行,每行给出1个18位身份证号码。

#include <stdio.h>
#define MAXN 100
 
int main(void) {
    int sum, Z, n, i, count = 0, j, k, weight[] = { 7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2 }, wrong = 0;
    char M[] = { '1','0','X','9','8','7','6','5','4','3','2' }, id[MAXN][20];
 
    scanf("%d", &n);
    for (i = 0; i < n; i++) {
        sum = 0;
        scanf("%s", id[i]);
        for (j = 0; j < 18; j++) {
            if (j < 17) {
                if (id[i][j] >= '0'&&id[i][j] <= '9') {
                    sum += (id[i][j] - '0') * weight[j];
                }
                else {
                    wrong = 1;
                    break;
                }
            }
            else {
                Z = sum % 11;
                if (id[i][j] != M[Z]) {
                    wrong = 1;
                }
            }
        }
        if (wrong) {
            printf("%s\n", id[i]);
            count++;
            wrong = 0;
        }
    }
    if (count == 0) {
        printf("All passed\n");
    }
 
    return 0;
}

7-56 福到了 (15point(s))
“福”字倒着贴,寓意“福到”。不论到底算不算民俗,本题且请你编写程序,把各种汉字倒过来输出。这里要处理的每个汉字是由一个 N × N 的网格组成的,网格中的元素或者为字符 @ 或者为空格。而倒过来的汉字所用的字符由裁判指定。

输入格式:
输入在第一行中给出倒过来的汉字所用的字符、以及网格的规模 N (不超过100的正整数),其间以 1 个空格分隔;随后 N 行,每行给出 N 个字符,或者为 @ 或者为空格。

输出格式:
输出倒置的网格,如样例所示。但是,如果这个字正过来倒过去是一样的,就先输出bu yong dao le,然后再用输入指定的字符将其输出。

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
	int n;
	bool flag = true;
	char c;
	string s[110], x[110];
	cin >> c >> n;	
	getchar();
	for (int i = 0; i < n; i++) {
		getline(cin, s[i]); 
		x[i] = s[i];
		reverse(s[i].begin(), s[i].end());
	}
	for (int i = 0; i < n; i++) {
		if (x[i] != s[n - i - 1]) flag = false;
	}
	if (flag == true) cout << "bu yong dao le\n";
	for (int i = n - 1; i >= 0; i--) {
		for (int j = 0; j < s[i].size(); j++) {
			if (s[i][j] == ' ') cout << " ";
			else cout << c;
		}
		cout << endl;
	}
	return 0;
} 

7-57 有理数比较 (10point(s))
本题要求编写程序,比较两个有理数的大小。

输入格式:
输入在一行中按照“a1/b1 a2/b2”的格式给出两个分数形式的有理数,其中分子和分母全是整形范围内的正整数。

输出格式:
在一行中按照“a1/b1 关系符 a2/b2”的格式输出两个有理数的关系。其中“>”表示“大于”,“<”表示“小于”,“=”表示“等于”。

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<iomanip>
using namespace std;
int main()
{
	int a1, b1, a2, b2;
	char a;
	cin>>a1>>a>>b1>>a2>>a>>b2;
	if(double(a1)/b1 > double(a2)/b2)
	{
		cout<<a1<<"/"<<b1<<" > "<<a2<<"/"<<b2;
	}
	if(double(a1)/b1 < double(a2)/b2)
	{
		cout<<a1<<"/"<<b1<<" < "<<a2<<"/"<<b2;
	}
	if(double(a1)/b1 == double(a2)/b2)
	{
		cout<<a1<<"/"<<b1<<" = "<<a2<<"/"<<b2;
	}
	return 0;
}

7-58 有理数加法 (15point(s))
本题要求编写程序,计算两个有理数的和。

输入格式:
输入在一行中按照a1/b1 a2/b2的格式给出两个分数形式的有理数,其中分子和分母全是整形范围内的正整数。

输出格式:
在一行中按照a/b的格式输出两个有理数的和。注意必须是该有理数的最简分数形式,若分母为1,则只输出分子。

#include<iostream>
#include<string>
#include<algorithm>
#include<vector>
#include<iomanip>

using namespace std;
int gcd(int a, int b);
int main()
{
	int a1, b1, a2, b2;
	char a;
	cin>>a1>>a>>b1>>a2>>a>>b2;
	int z = a1*b2 + a2*b1, m = b1*b2;
	int c = gcd(z, m);
//	cout<<c<<" "<<z<<" "<<m<<endl;
	if(m == c)
	{
		cout<<z /c;
	}else{
		cout<<z/c<<"/"<<m/c;
	}
	return 0;
}
int gcd(int a, int b)
{
	if(b == 0)
	{
		return a;
	}else{
		return gcd(b, a % b);
	}
}

7-59 大炮打蚊子 (15point(s))
现在,我们用大炮来打蚊子:蚊子分布在一个M×N格的二维平面上,每只蚊子占据一格。向该平面的任意位置发射炮弹,炮弹的杀伤范围如下示意:

O
OXO
O
其中,X为炮弹落点中心,O为紧靠中心的四个有杀伤力的格子范围。若蚊子被炮弹命中(位于X格),一击毙命,若仅被杀伤(位于O格),则损失一半的生命力。也就是说,一次命中或者两次杀伤均可消灭蚊子。现在给出蚊子的分布情况以及连续k发炮弹的落点,给出每炮消灭的蚊子数。

输入格式:
第一行为两个不超过20的正整数M和N,中间空一格,表示二维平面有M行、N列。

接下来M行,每行有N个0或者#字符,其中#表示所在格子有蚊子。

接下来一行,包含一个不超过400的正整数k,表示发射炮弹的数量。

最后k行,每行包括一发炮弹的整数坐标x和y(0≤x<M,0≤y<N),之间用一个空格间隔。

输出格式:
对应输入的k发炮弹,输出共有k行,第i行即第i发炮弹消灭的蚊子数。

#include<stdio.h>
#include<math.h>
int main()
{
	int M,N,i,j,k,h,z,m=0,p,q,count=0,wenheng[500]={0},wenzong[500]={0},sheheng[500]={0},shezong[500]={0},jishu[30][30]={0};
	char a[30][30]={'\0'};
	scanf("%d %d",&M,&N);
	for(i=0;i<M;i++)
		scanf("%s",&a[i]);
	scanf("%d",&k);
	for(i=0;i<k;i++)
		scanf("%d %d",&sheheng[i],&shezong[i]);
	for(i=0;i<M;i++)
		for(j=0;j<N;j++)
			if(a[i][j]=='#')
			{
				wenheng[m]=i;
				wenzong[m++]=j;
			}
	for(i=0;i<k;i++)
	{
		h=sheheng[i];
		z=shezong[i];
		for(j=0;j<m;j++)
		{
			if(wenheng[j]==h&&wenzong[j]==z)
			{
				if(jishu[wenheng[j]][wenzong[j]]==1)
					jishu[wenheng[j]][wenzong[j]]++;
				else
					jishu[wenheng[j]][wenzong[j]]+=2;
			}
			if(fabs(wenheng[j]-h)==1&&fabs(wenzong[j]-z)==0||fabs(wenheng[j]-h)==0&&fabs(wenzong[j]-z)==1)
				jishu[wenheng[j]][wenzong[j]]++;
		}
		for(p=0;p<M;p++)
			for(q=0;q<N;q++)
				if(jishu[p][q]==2)
				{
					jishu[p][q]++;
					count++;
				}
		printf("%d\n",count);
		count=0;
	}
	return 0;
}

7-60 九宫格输入法 (15point(s))
假设有九宫格输入法键盘布局如下:

[ 1,.?! ] [ 2ABC ] [ 3DEF ]
[ 4GHI ] [ 5JKL ] [ 6MNO ]
[ 7PQRS ] [ 8TUV ] [ 9WXYZ ]
[ 0空 ]
注意:中括号[ ]仅为了表示键盘的分隔,不是输入字符。每个中括号中,位于首位的数字字符即是键盘的按键,按一下即可输入该数字字符。多次按同一个键,则输入的字符依次循环轮流,例如按两次3,则输入D;按5次7,则输入S;按6次2,则输入A。按键0的输入组合是0和空格字符,即按两次0输入空格。

你需要对于给定的按键组合,给出该组合对应的文本。

输入格式:
输入在一行中给出数个字符的按键组合(例如 999 表示按3次9),每个字符的按键组合之间用空格间隔,最后一个输入法组合之后以换行结束。输入数据至少包括一个字符的按键组合,且输入总长度不超过500个字符。

输出格式:
在一行中输出该按键组合对应的文本。

#include<iostream>
#include<string>
#include<iomanip>
#include<algorithm>
using namespace std;
int main()
{
	string str[10] = {"0 ", "1,.?!","2ABC","3DEF","4GHI","5JKL","6MNO","7PQRS","8TUV","9WXYZ"};
	string x;
	getline(cin, x);
	int count = 0;
	for(int i = 0; i < x.length(); i++)
	{
		if(i+1 == x.length())
		{
			count++;
			cout<<str[x[i] - '0'][count % str[x[i] - '0'].length() - 1];
			break;
		}
		if(x[i] == ' ')
		{
			cout<<str[x[i - 1] - '0'][(count - 1) % (str[x[i - 1] - '0'].length() )]; 
			count = 0;
			continue;	
		}else{
			count ++;		
		}
	}	
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值