哈尔滨理工大学软件与微电子学院程序设计竞赛(题解)

比赛原链接

【--------------前面纯水题--------------】

A - 抗议必胜 1

在这里插入图片描述

//A
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
 
#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
 
int main() {
    //freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin);
    printf("V     V\n");
    printf(" V   V \n");
    printf("  V V  \n");
    printf("   V   \n");
    return 0;
}

B - 疫情死亡率

在这里插入图片描述

//B
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
 
#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
 
int main() {
    //freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin);
    double a, b;
    scanf("%lf %lf", &a, &b);
    double ans = b / a * 100;
    printf("%.3lf", ans);
    printf("%\n");
    return 0;
}

C - 整除判断

在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
 
#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
 
int main() {
    //freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin);
    int m,n;
    scanf("%d %d", &m, &n);
    if (m % n == 0) printf("YES\n");
    else printf("NO\n");
    return 0;
}

D - 编程时间

在这里插入图片描述

//
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
 
#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
 
int main() {
    //freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin);
    int h1, m1, h2, m2;
    scanf("%d %d %d %d", &h1, &m1, &h2, &m2);
    int mins = h2 * 60 + m2 - m1 - h1 * 60;
    int h3 = mins / 60;
    int m3 = mins - h3 * 60;
    printf("%d %d\n", h3, m3);
    return 0;
}

E - 双位彩

在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;

#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}

int main() {
	//freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin); 
	int a, b;
	scanf("%d %d", &a, &b);
	if (a == b) {
		printf("100\n");
	}
	else {
		int a1 = a /10;
		int a2 = a % 10;
		int b1 = b / 10;
		int b2 = b % 10;
		if (a1 == b2 && a2 == b1) {
			printf("20\n");
		}
		else {
			if (a1 != b1 && a1 != b2 & a2 != b1 && a2 != b2) {   //不中奖
				printf("0\n");
			}
			else {
				printf("2\n");
			}
		}
	}
	return 0;
}

F - 抗疫必胜2

在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
 
#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
 
int main() {
    //freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin);
    int n;
    scanf("%d", &n);
    for (int i = 0; i < n; ++ i) {
        printf("China will win the battle against COVID-19.\n");
    }
    return 0;
}

G - 成绩统计

在这里插入图片描述

//
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
 
#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
 
int main() {
    //freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin);
    int n;
    scanf("%d", &n);
    double sum = 0;
    int maxx = -1, minn = 101;
    int m = n;
    while(m--) {
        int a;
        scanf("%d", &a);
        sum += a;
        maxx = max(maxx, a);
        minn = min(minn, a);
    }
    printf("%.2lf %d %d", sum / n, maxx, minn);
    return 0;
}

H - 抗疫必胜3

在这里插入图片描述
【思路】:按照 “ 空格-V-空格-V ” 计算位置输出

#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
 
#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
 
int main() {
    //freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin);
    int n;
    scanf("%d", &n);
    int heng = 2 * n - 1;
    for (int i = 0; i < n - 1; ++ i) {
        int a = i;
        while (a > 0) {
            printf(" ");
            -- a;
        }
        printf("V");
        int mid = heng - 2 - i * 2;
        while (mid > 0) {
            printf(" ");
            -- mid;
        }
        printf("V\n");
    }
    -- n;
    while (n > 0) {
        printf(" ");
        -- n;
    }
    printf("V\n");
    return 0;
}

I - 统计数据

在这里插入图片描述
【思路】:因为数值的范围不大,开数组就可以代替哈希表。

#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
 
#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
int nums[10020];
int main() {
    //freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin);
    int n;
    scanf("%d", &n);
    while (n --) {
        int a;
        scanf("%d", &a);
        ++ nums[a];
    }
    for (int i = 10010; i >= 1; -- i) {
        if (nums[i] > 0) {
            printf("%d-%d\n", i, nums[i]);
        }
    }
    return 0;

J - 子序列求和

在这里插入图片描述
【思路】:前缀和的思想,nums数组第 i 个位置存的不是第 i 个数的值,而是前 i 个数的值,需要获取区间[ p , q ]之和的时候,即是获取 nums [ q ] - nums [ p - 1 ] 的值。但是这道题还需要考虑 p、q 取值是否合法:q 最大只能取到nums.length, p 至少得大于等于 1.

//
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
 
#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
int nums[1020];
int main() {
    //freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin);
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; ++ i) {
        scanf("%d", &nums[i]);
        nums[i] += nums[i - 1];
    }
    int t;
    scanf("%d", &t);
    while (t --) {
        int p, q;
        scanf("%d %d", &p, &q);
        q = min(q, n);
        if (p > n) {
            printf("0\n");
        }
        else {
            printf("%d\n", nums[q] - nums[p - 1]);
        }
    }
    return 0;
}

K - Simple Question

在这里插入图片描述
【思路】
在 1 - k 的区间内找能同时被m、n整除的最大数,那么可以先找出能同时被m、n整除的最小数num,再去考虑在区间1 - k 之间是否能将num翻几倍,还是num本身已经大于k。
① 求num:
假如 m = 6, n = 20,那么由 m = 2 * 3, n = 2 * 2 * 5(需要是质因子),可得出num = 2 * 2 * 3 * 5 = 60, 换而言之,对于同样有的质因子 2,num是根据到底max (m-2, n-2)来决定需要乘几个2。(m-2 表示m里面有几个因子2)。
②求max:
假如num > k,返回 1;否则k - 不能整除的部分即为所求,即返回: k - k % num。

//K
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;

#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
int nn[1020];
int mm[1020];

int main() {
	//freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin); 
	int n, m, k;
	scanf("%d %d %d", &n, &m, &k);
	int chushu = 2;
	//将n所有因子放在nn里面
	while (n != 1) {
		while (n % chushu == 0) {
			++ nn[chushu];
			n /= chushu;
		}
		++ chushu;
	}
	chushu = 2;
	//将m所有因子放在mm里面
	while (m != 1) {
		while (m % chushu == 0) {
			++ mm[chushu];
		    m /= chushu;
		}
		++ chushu;
	}
	long long num = 1;
	//得到num
	for (int i = 2; i < 1005; ++ i) {
		if (nn[i] != 0 || mm[i] != 0) {
			int maxx = max(nn[i], mm[i]);
			num *= pow(i, maxx);
		}
	}
	//考虑 1 - k 范围内的最大值
	if (num > k) printf("-1\n");
	else {
		num = k % num;
		printf("%d\n", k - num);
	}
	return 0;
}

L - Wrong Word

在这里插入图片描述
【思路】
实质上是排列组合

#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
 
#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
char str[11];
char book[26];
int main() {
    //freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin);
    scanf("%s", &str);
    int cnt = 0;   //计算有多少个字母(包括重复)
    for (int i = 0; i < 11; ++ i) {
        if (str[i] - 'A' >= 0 && str[i] - 'Z' <= 0) {
            int index = str[i] - 'A';
            ++ cnt;
            ++ book[index];
        }
         
    }
    long long ans = 1;
    //计算 A 的 n 取 n
    while (cnt != 1) {
        ans *= cnt;
        -- cnt;
    }
    //去除 重复字母重复计算的数量
    for (int i = 0; i < 26; ++ i) {
        if (book[i] > 1) {
            cnt = book[i];
            while (cnt != 1) {
                ans /= cnt;
                -- cnt;
            }
        }
    }
    //cout << ans << endl;
    printf("%lld", ans - 1);
     
    return 0;
}

M - Mutable Array

在这里插入图片描述
在这里插入图片描述
【思路】
推导公式,剩下的n - 2个数只能取minn - maxx之间的数,那么这n - 2个数之和的范围只能是(n - 2)* minn 到 (n - 2) * maxx 之间,故而结果为 (n - 2) * (maxx - minn) + 1.

#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
 
#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
 
int main() {
    //freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin);
    long long n, minn, maxx;
    scanf("%lld %lld %lld", &n, &minn, &maxx);
    long long ans = (maxx - minn) * (n - 2) + 1;
    printf("%lld\n", ans);
    return 0;
}

N - Interesting Number

在这里插入图片描述
【思路】:
因子数 == 3,即除了1和它本身,只有一个另外的因子。换句话说就是需要刚好能开方,但是不仅于此,因为诸如16能开方为4,4不是质数,所以16还能被4的因子整除。故而满足要求的数应当是:只有三个因子,除了1、本身,另外一个因子是质数。

做法:先打一个素数表,计算有多少个素数a小于等于num / a(即a ^ 2<= num,但是为了防止数据溢出,所以将一个a移到右边)。

//N
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
 
#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
int primes[10000030], cnt;     // primes[]存储所有素数
bool st[10000030];         // st[x]存储x是否被筛掉
 
void get_primes(int n)
{
    for (int i = 2; i <= n; i ++ )
    {
        if (!st[i]) primes[cnt ++ ] = i;
        for (int j = 0; primes[j] <= n / i; j ++ )
        {
            st[primes[j] * i] = true;
            if (i % primes[j] == 0) break;
        }
    }
}
 
 
int main() {
    //freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin);
    get_primes(10000000);
    long long num;
    scanf ("%lld", &num);
    long long falg = 2;
    long long ans = 0;
    while (falg <= num / falg) {
        if (! st[falg]) ++ ans;
        ++ falg;
    }
    printf("%lld", ans);
    return 0;
}

O - Find Difference

在这里插入图片描述
【思路】
假设只有一堆,那么不用称也知道是2g。
而对于多堆,给每一堆从1 至 n 编上号,对于第 i 堆取出 i 枚硬币,原本如果硬币都是 1 g,那么重量应该是 W =(1 + n)* n / 2,所以将电子秤的称得的重量 - W 就能知道是第几堆。故而只需要称一次

// O
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
 
#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
 
int main() {
    //freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin);
    long long n;
    scanf("%lld", &n);
    if (n == 1) printf("0");
    else printf("1");
    return 0;
}

P - Dismantling Number

在这里插入图片描述
【思路】
直接暴力……int范围内的数每一层循环最多也就执行31次……

//P
#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
 
#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
 
int main() {
    //freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin);
    int n;
    scanf("%d", &n);
    long long nums[32];
    for (int i = 1; i < 32; ++ i) {
        nums[i] = pow(2, i);
    }
    int i, j, k;
    bool falg = false;
    for (i = 1; i < 32; ++ i) {
        for (j = 1; j < 32; ++ j) {
            for (k = 1; k < 32; ++ k) {
                if (nums[i] + nums[j] + nums[k] == n) {
                    //cout << nums[i] << " "<< nums[j] << " "<< nums[k] <<" " << n;
                    falg = true;
                    break;
                }
            }
            if (falg) break;
        }
        if (falg) break;
    }
    if (i == 32 && j == 32 && k == 32) {
        printf("NO\n");
    }
    else {
        printf("YES\n");
    }
    return 0;
}

Q - Finite Decimal

在这里插入图片描述
【思路】
只有无理数才会无限不循环,所以对于有理数来说,只需要考虑无限循环和有限小数。
那么由于是用 1 去除,其实可以看成是一个足够大的 1 * 10 ^ x 能不能被 n 整除。进而可以推出问题的解决就是要看 n 的因子是不是除了 1 和 它本身以外,最多只有 2 和 5,因为 2 * 5 == 10。

#include<iostream>
#include<algorithm>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>
using namespace std;
 
#define getlength(array,len) {len = (sizeof(array) / sizeof(array[0]));}
 
int main() {
    //freopen("D:\\a-日常文档使用\\输入数据.txt", "r", stdin);
    int t;
    scanf("%d", &t);
    while (t --) {
        int n;
        scanf("%d", &n);
        while (n % 2 == 0) {
            n /= 2;
        }
        while (n % 5 == 0) {
            n /= 5;
        }
        if (n == 1) printf("YES\n");
        else printf("NO\n");
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值