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 ++;
}
}
}