自测-1 打印沙漏
本题要求你写个程序把给定的符号打印成沙漏的形状。例如给定17个“*”,要求按下列格式打印
*****
***
*
***
*****
所谓“沙漏形状”,是指每行输出奇数个符号;各行符号中心对齐;相邻两行符号数差2;符号数先从大到小顺序递减到1,再从小到大顺序递增;首尾符号数相等。
给定任意N个符号,不一定能正好组成一个沙漏。要求打印出的沙漏能用掉尽可能多的符号。
输入格式:
输入在一行给出1个正整数N(≤1000)和一个符号,中间以空格分隔。
输出格式:
首先打印出由给定符号组成的最大的沙漏形状,最后在一行中输出剩下没用掉的符号数。
输入样例:
19 *
输出样例:
*****
***
*
***
*****
2
解题思路:
这个题目还是比较简单,属于入门级别,我首先想到的办法是:观察+结合数学知识。
对于这个题,只要知道漏斗层数即可。
通过以上分析,不难得到漏斗层数的最大值,接下来用编程语言模拟出打印过程即可。具体代码如下:
#include <bits/stdc++.h>
using namespace std;
int main() {
int a;
char b;
cin >> a >> b;
int y = int(sqrt((a + 1) / 2));//y表示上层漏斗的层数
int answer = a + 1 - 2 * y * y;//answer表示剩余字符个数
for (int i = y; i > 0; i--) {//打印上层漏斗,i控制层数
for (int k = 0; k < (y - i); k++) {//k控制每层的空格数,空格数与层数相关
cout << " ";
}
for (int j = 0; j < 1 + (i - 1) * 2; j++) {//j控制每层的字符数,遵守等比数列通项公式
cout << b;
}
cout << endl;
}
for (int i = 2; i <= y; i++) {//下层漏斗需要少打一层,同时要“倒”着打印,其余与上层漏斗同理
for (int k = 0; k < (y - i); k++) {
cout << " ";
}
for (int j = 0; j < 1 + (i - 1) * 2; j++) {
cout << b;
}
cout << endl;
}
cout << answer;//无论剩余字符多少都需要打印出来,如果有朋友只有18分,大概率是因为在answer=0时未输出answer的值,应该是理解错题目意思了
return 0;
}
自测-2 素数对猜想
让我们定义dn为:dn=pn+1−pn,其中pi是第i个素数。显然有d1=1,且对于n>1有dn是偶数。“素数对猜想”认为“存在无穷多对相邻且差为2的素数”。
现给定任意正整数N
(<),请计算不超过
N
的满足猜想的素数对的个数。
输入格式:
输入在一行给出正整数N
。
输出格式:
在一行中输出不超过N
的满足猜想的素数对的个数。
输入样例:
20
输出样例:
4
解题思路:
这个题相对来说也比较简单,主要考察质数的含义。首先,什么是质数?质数是指在大于1的自然数中,除了1和它本身以外不再有其他因数的自然数。题目中给出了N,要求不超过N的满足猜想的素数对,不难想到,最简单的办法就是遍历不超过N的所有素数,然后判断其是否满足猜想,若满足,就计入数量,最终输出总的数量即可。
代码如下:
#include <bits/stdc++.h>
using namespace std;
int main() {
int a, count = 0, temp = 2; //count用于记录满足猜想的素数对个数,temp用于暂存前一个素数
cin >> a;
for (int i = 2; i <= a; i++) { //遍历不超过a的所有数
int flag = 1; //标志变量用于判断i是否是质数
for (int j = 2; j * j <= i; j++) { //列举可能的因数
if (i % j == 0) { //%表示取余数,若能整除,说明除了1和他本身外还有别的因数,因此将其标志为合数,并及时退出循环
flag = 0;
break;
}
}
if (flag) {//表示当前这个数是素数
if ((i - temp) == 2) { //表示如果当前这个素数与前一个素数之差为2,则这两个素数符合猜想
//这里注意temp的初始值不可为0,因为如果为0,那么第一个素数“2”会被单独列为素数对,显然不符合题意
count++;
}
temp = i;//只要是素数就要更新temp的值
}
}
cout << count;
return 0;
}
自测-3 数组元素循环右移问题
一个数组A中存有N(>0)个整数,在不允许使用另外数组的前提下,将每个整数循环向右移M(≥0)个位置,即将A中的数据由(A0A1⋯AN−1)变换为(AN−M⋯AN−1A0A1⋯AN−M−1)(最后M个数循环移至最前面的M个位置)。如果需要考虑程序移动数据的次数尽量少,要如何设计移动的方法?
输入格式:
每个输入包含一个测试用例,第1行输入N(1≤N≤100)和M(≥0);第2行输入N个整数,之间用空格分隔。
输出格式:
在一行中输出循环右移M位以后的整数序列,之间用空格分隔,序列结尾不能有多余空格。
输入样例:
6 2
1 2 3 4 5 6
输出样例:
5 6 1 2 3 4
解题思路:
这道题相对来说比较简单,要注意的是m在题目中只给出了大于零的条件,因此它可能比n大,真实的位移就可以通过m%n来得到(如果不取整,假设m=7,n=5,那就不方便用“最后M个数循环移至最前面的M个位置”这个办法来做了。因为你咋确定最后7个数是哪些呢?总共只有5个数,对吧。那为什么要取整呢,你想一下,你把这5个数中的第一个数挨个循环右移5个位置,它其实最后又回到了第一个位置,右移10个位置也一样。因为总长度是5,如果循环右移的长度是总长度的倍数,那它总会回到原位置的,那也就意味着总长度的倍数的那些移动是没有必要的,是浪费时间的,那不正好通过取余来解决?我只关心余数是多少。(可能我说的比较啰嗦,大家要是还不能理解,可以在草稿纸上画一画哦))
代码如下:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, m;
cin >> n >> m;
int r = m % n; //真实右移位数,因为m可能比n大
int a[n + r + 5];
// 由题可知,要让后m个(实际是r个)数平行移到前面r个数的位置上
//由于移动的位置已知,而前后两部分的顺序不变,因此直接在输入的时候就可以实现置换
for (int i = r; i < n; i++) {//因为后m个数移动到了前面,因此,前面那些数就必须存到后面的位置上,即留出m个(实际是r个)数的位置来
cin >> a[i];
}
for (int i = 0; i < r; i++) {//这里表示后m个(实际是r个)数平行移到前面r个数的位置上
cin >> a[i];
}
for (int i = 0; i < n - 1; i++) {//重新打印输出
cout << a[i] << " ";
}
cout << a[n - 1]; //注意题目要求结尾不能有多余空格
return 0;
}
自测-4 Have Fun with Numbers
Notice that the number 123456789 is a 9-digit number consisting exactly the numbers from 1 to 9, with no duplication. Double it we will obtain 246913578, which happens to be another 9-digit number consisting exactly the numbers from 1 to 9, only in a different permutation. Check to see the result if we double it again!
Now you are suppose to check if there are more numbers with this property. That is, double a given number with k digits, you are to tell if the resulting number consists of only a permutation of the digits in the original number.
Input Specification:
Each input contains one test case. Each case contains one positive integer with no more than 20 digits.
Output Specification:
For each test case, first print in a line "Yes" if doubling the input number gives a number that consists of only a permutation of the digits in the original number, or "No" if not. Then in the next line, print the doubled number.
Sample Input:
1234567899
Sample Output:
Yes
2469135798
解题思路:
这道题考察的是对数字的处理能力。整体来说比较简单,就直接放代码了吧。要注意的点在于这个题输入的数字很可能超过了unsigned long long的范围,因此输入应该采取字符串的形式,要不然总会有两个测试集无法通过。
#include <bits/stdc++.h>
using namespace std;
int main() {
string a;
cin >> a;
int c[15], d[25], add = 0, orig, index = -1, len = a.length(), temp; //add表示进位,orig表示本位
string s = "";
memset(d, 0, sizeof(d)); //d用于存放a*2后所得结果的逆序
memset(c, 0, sizeof(c)); //c数组用于存放a各数字的个数
for (int i = len - 1; i >= 0; i--) { //从个位向高位遍历a各个数位上的数字个数,并计入c中
temp = int(a[i] - '0');
orig = (temp * 2 + add) % 10;
d[++index] = orig;
add = (temp * 2 + add) / 10;
c[temp]++;
}
if (add) {
d[++index] = add;//这里不要忘记最后结果的"高位"数字
}
for (int i = 0; i <= index; i++) {//将double后的数与a进行对比即可
c[d[i]]--;//若在c中出现过,就让次数--
s.push_back(d[index - i] + '0');
}
s.push_back('\0');
for (int i = 0; i < 11; i++) {
if (c[i] != 0) {
cout << "No" << endl;
cout << s << endl;
return 0;
}
}
cout << "Yes" << endl;
cout << s << endl;
return 0;
}
自测-5 Shuffling Machine
Shuffling is a procedure used to randomize a deck of playing cards. Because standard shuffling techniques are seen as weak, and in order to avoid "inside jobs" where employees collaborate with gamblers by performing inadequate shuffles, many casinos employ automatic shuffling machines. Your task is to simulate a shuffling machine.
The machine shuffles a deck of 54 cards according to a given random order and repeats for a given number of times. It is assumed that the initial status of a card deck is in the following order:
S1, S2, ..., S13,
H1, H2, ..., H13,
C1, C2, ..., C13,
D1, D2, ..., D13,
J1, J2
where "S" stands for "Spade", "H" for "Heart", "C" for "Club", "D" for "Diamond", and "J" for "Joker". A given order is a permutation of distinct integers in [1, 54]. If the number at the i-th position is j, it means to move the card from position i to position j. For example, suppose we only have 5 cards: S3, H5, C1, D13 and J2. Given a shuffling order {4, 2, 5, 3, 1}, the result will be: J2, H5, D13, S3, C1. If we are to repeat the shuffling again, the result will be: C1, H5, S3, J2, D13.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer K (≤20) which is the number of repeat times. Then the next line contains the given order. All the numbers in a line are separated by a space.
Output Specification:
For each test case, print the shuffling results in one line. All the cards are separated by a space, and there must be no extra space at the end of the line.
Sample Input:
2
36 52 37 38 3 39 40 53 54 41 11 12 13 42 43 44 2 4 23 24 25 26 27 6 7 8 48 49 50 51 9 10 14 15 16 5 17 18 19 1 20 21 22 28 29 30 31 32 33 34 35 45 46 47
Sample Output:
S7 C11 C10 C12 S1 H7 H8 H9 D8 D9 S11 S12 S13 D10 D11 D12 S3 S4 S6 S10 H1 H2 C13 D2 D3 D4 H6 H3 D13 J1 J2 C1 C2 C3 C4 D1 S5 H5 H11 H12 C6 C7 C8 C9 S2 S8 S9 H10 D5 D6 D7 H4 H13 C5
解题思路:
这道题也比较简单,关键在于看懂题目,注意事项如下:
- Shuffling是洗牌的意思,在其他编程题中也可能会出现,要注意积累
- 给string追加数字,用to_string(num);
- 注意书写规范,切勿马虎写成(12<num<=26)
代码如下:
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
cin >> n;
int a[60];
string b[60], c[60]; //b数组存放当前状态,c数组作为辅助数组
for (int i = 1; i < 55; i++) {
cin >> a[i];
if (i <= 13) {
b[i] = "S" + to_string(i);
}
if (13 < i && i <= 26) {
b[i] = "H" + to_string(i - 13);
}
if (26 < i && i <= 39) {
b[i] = "C" + to_string(i - 26);
}
if (39 < i && i <= 52) {
b[i] = "D" + to_string(i - 39);
}
if (52 < i && i <= 54) {
b[i] = "J" + to_string(i - 52);
}
}
for (int j = 0; j < n; j++) {
for (int i = 1; i < 55; i++) {
c[a[i]] = b[i];
}
for (int k = 1; k <= 54; k++) { //每次洗牌都应更新b数组
b[k] = c[k];
}
}
for (int i = 1; i <= 53; i++) {
cout << b[i] << " ";
}
cout << b[54];
return 0;
}
第一次尝试写博客,经验不足,希望大家多多指点,欢迎大家在评论区交流讨论。