航空航天大类C语言程设第三次上机练习
第三期更新,是第三次上机的内容(由于第三次练习赛每个题都有写头,这次就更这么多
Q1(上机A题)有一个小于2322^{32}232的正整数。他发现这个数在现在的绝大多数机器上可以用一个32位的二进制数表示(不足32位用0补足)。他称这个二进制数的前16位为“高位”,后16位为“低位”。将它的高低位交换,可以得到一个新的数。他想知道这个新的数是多少(用十进制表示)。
例如,数1314520用二进制表示为0000 0000 0001 0100 0000 1110 1101 1000(添加了11个前导0补足为32位),其中前16位为高位,即0000 0000 0001 0100;后16位为低位,即0000 1110 1101 1000。将它的高低位进行交换,我们得到了一个新的二进制数0000 1110 1101 1000 0000 0000 0001 0100。它即是十进制的249036820。
输入一个小于2322^{32}232的正整数,输出交换高低位后的整数(这里高低位交换是对unsigned操作)
注意第一点,用unsigned int
的好处在于范围在0~4294967296所以保证不会溢出(至于为什么考虑溢出后面再说),当然读入方式就不一样,用scanf("%u",&n)
方法读入
然后是怎么做,题目的例子已经提示的很明显了,一个数的后16位如何到前面去和前16位如何到后面去,肯定会涉及到位运算的移位操作,观察例子的二进制表示,一个数,退16位,前16位全为0,后16位是之前的16位,进16位,前16位由后面的16位顶上而后16位全为0,这两个应该可以通过一种操作并为一个数,那么答案只有一个了,就是做或运算了,两个数或运算,比如0000 0000 0000 0000 0000 0000 0001 0100和0000 1110 1101 1000 0000 0000 0000 0000或运算就是0000 1110 1101 1000 0000 0000 0001 0100
代码
#include<stdio.h>
int main(){
unsigned int n;
scanf("%u", &n);
printf("%u", (n >> 16)|(n << 16));
return 0;
}
Q2(上机C题)
一场比赛将开始于h1:m1h1:m1h1:m1,结束于h2:m2h2:m2h2:m2,现在需要求出这场比赛的中间时刻
输入:
第一行包含两个整数h1,m1h1,m1h1,m1,第二行包含两个整数h2,m2h2,m2h2,m2
保证0≤h1,h2≤23,0≤m1,m2≤590 \le h1,h2\le23,0\le m1,m2\le590≤h1,h2≤23,0≤m1,m2≤59,且m1%2=m2%2m1 \%2 = m2 \% 2m1%2=m2%2。
保证开始时间和结束时间在同一天且开始时间早于结束时间。
输出:两个整数h3,m3h3,m3h3,m3表示比赛的中点时间。
注意时间必须是xx:xx的格式!比如 01:02
由于分钟对2同余,所以可以保证中间时刻分钟是整数,求法也很简单,两个时间相对0时0分过去的分钟数取平均(相当于求中点),再化成xx:xx的形式就是中间时刻了,也注意到注意事项了吧,小时和分钟都得输出两位,对于小于10的数要注意了,当然熟悉格式化输出就没有问题,介绍一下printf("%02d", n)
的格式化输出,意思是输出一个整数,必须是两位,不足的用0补前位,是不是一下子就好了呢ヽ( ̄▽ ̄)ノ
#include<stdio.h>
int main() {
int h1, m1, h2, m2, h3, m3, t;
scanf("%d:%d", &h1, &m1);
scanf("%d:%d", &h2, &m2);
t = ((h2 * 60 + m2) + (h1 * 60 + m1)) / 2;
printf("%02d:%02d", t / 60, t % 60);
return 0;
}
Q3(上机E题)货物重量
有一批货要被运送,但是负责联系的人忘记货物重多少。他只记得货物的重量为w(1≤w≤105)w(1\le w\le105)w(1≤w≤105)(单位吨),还好他记得货物的重量模3、5、7的余数即w%3、w%5、w%7w\%3、w\%5、w\%7w%3、w%5、w%7,但是他不知道如何通过余数求出体重,你能帮帮他吗?
多组测试数据
每组数据一行三个自然数(包括零的那种自然数)用空格隔开,分别小于3、5、7,表示w%3、w%5、w%7w\%3、w\%5、w\%7w%3、w%5、w%7。
对于每组数据,输出一行一个整数www。
多组测试数据指的是数据组数不一定,需要持续读入直到EOF
(End Of File)
第一种比较好像的处理方法,鉴于数据范围是1到105,自然可以遍历验证余数是不是满足条件(这里暂时省去主函数)
int weight(int x, int y, int z) {
int p, w;
for (p = 1; p <= 105; p++) {
if (p % 3 == x && p % 5 == y && p % 7 == z) {
w = p;
break;
}
}
return w;
}
当然这个题肯定是有更好的做法,这其实是一个典型的同余方程
{
a≡x(mod3)a≡y(mod5)a≡z(mod7)\begin{cases} a\equiv x\pmod{3}\\ a\equiv y\pmod{5}\\ a\equiv z\pmod{7}\\ \end{cases}⎩⎪⎨⎪⎧a≡x(mod3)a≡y(mod5)a≡z(mod7)
x,y,zx,y,zx,y,z是每组数据读入的三个w%3、w%5、w%7w\%3、w\%5、w\%7w%3、w%5、w%7,幸运的是模3、5、7互质,所以可以用中国剩余定理,且方程组一定有解,可以这样构造方程组的解:
一般地对于这样一个同余方程组:
{
x≡a1(modm1)x≡a2(modm2)...x≡an(modmn)\begin{cases} x\equiv a_1\pmod{m_1}\\ x\equiv a_2\pmod{m_2}\\ ...\\ x\equiv a_n\pmod{m_n}\\ \end{cases}⎩⎪⎪⎪⎨⎪⎪⎪⎧x≡a1(modm1)