🏑1.3 图形输出
有些题目会给出一定的规则,需要我们来根据规则画出对应的图形,其实就是由若干字符按照一定的规则输出。一般分为两种形式
通过规律直接输出。
定义一个二维字符数组,按照规律进行填充一次性输出。
看个例子。
【PAT B1036】 跟奥巴马一起编程 (15 分)
题目描述
美国总统奥巴马不仅呼吁所有人都学习编程,甚至以身作则编写代码,成为美国历史上首位编写计算机代码的总统。2014 年底,为庆祝“计算机科学教育周”正式启动,奥巴马编写了很简单的计算机代码:在屏幕上画一个正方形。现在你也跟他一起画吧!
输入格式:
输入在一行中给出正方形边长 N(3≤N≤20)和组成正方形边的某种字符 C,间隔一个空格。
输出格式:
输出由给定字符 C 画出的正方形。但是注意到行间距比列间距大,所以为了让结果看上去更像正方形,我们输出的行数实际上是列数的 50%(四舍五入取整)。
样例输入
10 a
样例输出
aaaaaaaaaa
a a
a a
a a
aaaaaaaaaa
解题思路
由于行数为列数的一半,如果列数是偶数的时候,行数就是n/2;如果列数是奇数的时候,行数就是n/2+1,不如做个统一都是(n+1)/2。
通过分析发现,由三部分组成,第1行和第row行都是输出n个a,对于第2~row-1的每一行,都是先输出一个a最后再输出一个a,然后中间输出col-2个a。
所以我们而已先输出一个a,然后输出row-2个空格,然后输出一个a。
参考代码
#include<cstdio> int main(){ int row, col; char c; scanf("%d %c",&col,&c); row = (col +1)/2; //选取行数 for(int i = 0;i < row;i++){ if(i == 0 || i == row -1){ for(int j = 0;j < col;j++) printf("%c",c); puts(""); continue; } printf("%c",c);//输出第一个c for(int j = 0;j < col -2;j++) printf(" "); if(col > 1) printf("%c",c); puts(""); } return 0; }
🏏1.4 日期处理
日期的处理总会让人头疼,因为涉及到处理闰年的问题、大月小月的问题,因此细节比较繁杂,但是只要细心处理细节,这类问题就会很简单。
看个例子:
问题 A: 日期差值
题目描述
有两个日期,求两个日期之间的天数,如果两个日期是连续的我们规定他们之间的天数为两天。
输入格式:
有多组数据,每组数据有两行,分别表示两个日期,形式为YYYYMMDD
输出格式:
每组数据输出一行,即日期差值
样例输入
20130101
20130105
样例输出
5
解题思路
不妨设第一个日期早于第二个日期,如果不早交换就可以了。
有一个常用的思路:令日期不断的加1天,直到第一个日期等于第二个日期即可。
具体操作时:
如果加一天之后天数d等于当前月份m所拥有的天数+1,则令月份m+1,同时置天数为1;
如果月份加1后等于13,则年份加1,同时把月份变为1.
为了方便的计算每个月份的天数,不妨设置一个二维数组int month[13][2]来表示闰年和平年的每个月份的天数。
注意:如果想要加快速度,就将第一个日期的年份不断加1到与第二个年份相差1即可,期间根据年份来判断加365还是增加366,最后再不断令天数加1操作。
参考代码
#include<cstdio> int month[13][2] = {{0,0},{31,31},{28,29},{31,31},{30,30},{31,31},{30,30},{31,31},{31,31},{30,30},{31,31},{30,30},{31,31}}; bool isLeap(int year){ //有个口诀,四年一闰。百年不闰,四百年再闰 return (year % 4 == 0 && year % 100 != 0) || year % 400 == 0; } int main(){ int time1, y1, m1, d1; int time2, y2, m2, d2; while(scanf("%d %d", &time1, &time2) != EOF){ if(time1 > time2){ //swap time1 = time1 ^ time2; time2 = time1 ^ time2; time1 = time1 ^ time2; } y1 = time1 / 10000, m1 = time1 % 10000 / 100, d1 = time1 % 100; y2 = time2 / 10000, m2 = time2 % 10000 / 100, d2 = time2 % 100; int ans = 1; //当不相等的时候循环 while(y1 < y2 || m1 < m2 || d1 <d2){ d1++; if(d1 == month[m1][isLeap(y1)] + 1){ m1++; d1 = 1; } if(m1 == 13){ y1 ++; m1 = 1; } ans++; } printf("%d\n",ans); } return 0; }
🏂1.5 进制转换
日常生活使用的进制一般是十进制,而计算机使用的进制是二进制,另外还有八进制,十六进制以及各种数字进制,这就会产生一个问题:对于不同进制如何转换呢?
对于一个P进制转换为Q进制,需要分为两步
将P进制转换为十进制
这个的相关算法实现也很简单
int y = 0, product = 1;//product 不断乘p得到p的不同次方 while(x != 0){ y = y + (x % 10) * product;//每次取出最低位 看起来像十进制 x = x / 10; product *= p; }
将十进制转化为Q进制(大名鼎鼎的除留余数法)
例如要将11转化为2进制
11 / 2 商5 余1
5 /2 商2 余1
2/2 商1 余0
1/2 商0 余1
从下往上看 可以得到2进制为(1011)2
int z[40], num = 0; do{ z[num++] = y % Q; y /= Q; }while(y != 0);
这里使用do…while的原因是可以规避掉0的特殊处理
【PAT B1022】D进制的A+B (20 分)
题目描述
输入两个非负 10 进制整数 A 和 B (≤230−1),输出 A+B 的 D (1<D≤10)进制数。
输入格式:
输入在一行中依次给出 3 个整数 A、B 和 D。
输出格式:
输出 A+B 的 D 进制数。
样例输入
123 456 8
样例输出
1103
解题思路
先计算A+B的十进制,然后将结果转化为D进制,而十进制转化为D进制的可以使用除留余数法。
参考代码
#include<cstdio> int main(){ int a, b, d; scanf("%d %d %d", &a, &b, &d); int sum = a + b; int ans[31], num = 0; //ans存放d进制的没一位 do{ ans[num++] = sum % d; sum /= d; }while(sum != 0); for(int i = num - 1;i >= 0;i--) printf("%d",ans[i]); puts(""); return 0; }