2020级ACM协会招新测试题解
第一题:圣诞节买苹果
题意:就是求∑i=1N⌊n/i⌋\sum_{i=1}^N\lfloor n/i \rfloori=1∑N⌊n/i⌋
所以可以直接用一个循环来求
long long ans = 0;
for(int i = 1;i <= n;i++){
ans += n / i;
}
第二题:万圣节买糖
题意:和第一题一样,但是数据大小是1e13,直接用循环来做的话肯定会超时(时间限制是1000ms,如果运算次数超过1e7基本就会超时)。
所以这题应该用更简单的做法来写。
当n = 17的时候,我们发现。
我们在excel中查看⌊n/i⌋\lfloor n/i \rfloor⌊n/i⌋和i的关系:
我们可以看出当,i<=4,∀j∈(⌊n/(i+1)⌋,⌊n/i⌋]i <=4, {\forall} j \in (\lfloor n/(i+1)\rfloor,\lfloor n / i \rfloor ]i<=4,∀j∈(⌊n/(i+1)⌋,⌊n/i⌋]
⌊n/j⌋=i\lfloor n/j \rfloor = i⌊n/j⌋=i
即可以在O(n) O(\sqrt{n})O(n)时间内算出来。
O是时间复杂度符号。具体可以自己百度。
第三题万圣节发糖
直接放代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,a[3];
cin>>n>>a[0]>>a[1]>>a[2];//输入
sort(a,a+3);//排序
int t = n/a[0];
int w1,w2,w3;
int cnt = 0;
for(int i = t; i >= 0; i --)
{
w1 = n - i * a[0];
for(int j = w1 / a[1]; j >= 0; j --)
{
w2 = w1 - j * a[1];
if(w2 % a[2] == 0) {cnt=max(cnt,i+j+w2/a[2]);}
}
}
cout<<cnt<<endl;//输出
}
第四题 求和
1 + 2 + 3 + … n
n <= 1e9
用循环肯定会超时。
就是等差数列求和
ans=n∗(n+1)/2 ans = n * (n + 1) / 2ans=n∗(n+1)/2
时间杂度是O(1)O(1)O(1)
第五题 Winry的苹果派
题意:输入一个正整数x,判断是否能将其分成两个正的偶数;
显然只有当这个数为偶数的时候才满足条件,而2是最小的正偶数,不能再分割,除此之外任意一个大于2的偶数x都可以分成2和(x-2),所以只需要判断x是否为一个大于2的偶数即可
第六题 校庆日
题意:最少用多少个边长为a的小正方形,可以完全覆盖一个长为n宽为m的长方形;
显然只要求的就是⌈n/a⌉+⌈m/a⌉\lceil n/a \rceil + \lceil m/a \rceil ⌈n/a⌉+⌈m/a⌉
第七题 成绩单
题目意思就是给成绩从大到小排序。
这里介绍选择排序。
给定一个数组,这种思想首先假定数组的首元素为最大或者最小的。此时就要利用3个变量表示元素的下标。一个表示当前,一个表示找到的最大或者最小的下标,一个用于存放每次循环中最大值的下标。在掌握了程序的基本思想之后,再进行排序。找到最大的下标后赋给每次除非的那个最大的下标。找到之后判断所假设的当前值是否为此次循环的最大值,如果不是,就交换最大 与当前的值,从而将数组以一定的顺序排放,最后写一个循环将结果输出。
for(int i = 0;i < n;i++){
int miId = i;
for(int j = i;j < n;j++){
if(a[j] > a[miId])
miId = j;
}
int tmp = a[i];
a[i] = a[miId];
a[miId] = tmp;
}
第八题 A+B
略
第九题 A+B
这题数据量很大,需要用字符串来存整数。
第十题
略
第十一题
略
第十二题 判断素数
这题也是复杂的为O(n)O(\sqrt{n})O(n)
只要一个数在[2,n]之间没有因数,那么它就是素数只要一个数在[2,\sqrt{n}]之间没有因数,那么它就是素数只要一个数在[2,n]之间没有因数,那么它就是素数
这是一个结论。可以记一下。
第十三题 进制转换。
直接放代码吧
#include <stdio.h>
#define INF 0x3f3f3f3f
typedef long long ll;
const int mod = 1e9 + 7;
int M;
char num_char[40];
int dp[10005];
void solve(){
int a,b;
scanf("%d%d",&a,&b);
char ans[60];
int tot = 0;
while (a){
ans[tot++] = num_char[a % b];
a /= b;
}
for(int i = tot - 1;i >= 0;i--){
printf("%c",ans[i]);
}
puts("");
}
int main(){
for(int i = 0;i <= 9;i++){
num_char[i] = i + '0';
}
for(int i = 10;i < 36;i++){
num_char[i] = 'A' + (i - 10);
}
num_char[36] = '\0';
// cout << num_char << endl;
int t;
scanf("%d",&t);
while (t--)
solve();
return 0;
}