2020年十一届省赛大学B组真题(共10道题)
算法涉及:
- 模拟: A,B,C,D,F,G
- 数学: B,I
- 图论: E
- 贪心: H, J
(填) 试题 A: 门牌制作
算法: 模拟
:::success
思路: 用一个数组统计每个数出现的个数, 枚举即可
#include <iostream>
using namespace std;
int arr[20];
int main() {
for(int i=1;i<=2020;i++) {
int t=i;
while(t) {
int m=t%10;
t/=10;
arr[m]++;
}
}
cout<<arr[2];
return 0;
}
:::
(填) 试题 B: 既约分数
算法: 约数
模拟
:::success
思路: 知道gcd() 最大公约数, 就能写
#include <iostream>
using namespace std;
int gcd(int a, int b) {
return b==0?a:gcd(b, a%b);
}
int main() {
int ans=0;
for(int i=1;i<=2020;i++) {
for(int j=1;j<=2020;j++) {
if(gcd(i,j)==1) ans++;
}
}
cout<<ans;
return 0;
}
:::
(填) 试题 C: 蛇形填数
算法: 模拟
:::success
思路:
- 观察第二斜列, 2[2,1], 3[1,2] 和 第三斜列: 4[3,1], 5[2,2], 6[1,3];
- 结论一: 从i, j枚举到j, i为止, 每次i++, j–或反.
- 结论二: 由j和i的大小关系决定该往 下 或 右.
#include <iostream>
using namespace std;
int arr[100][100];
int main() {
int i=1, j=1, count=2;
arr[1][1]=1;
while(i<60) {
if(i>j) {
i++;
int t=i;
for(;j<t;i--,j++) arr[i][j]=count++;
arr[i][j]=count++;
}
else {
j++;
int t=j;
for(;i<t;i++,j--) arr[i][j]=count++;
arr[i][j]=count++;
}
}
cout<<arr[20][20];
return 0;
}
:::
(填) 试题 D: 跑步锻炼
算法: 模拟
:::success
思路:
- **结论1: **一个在2000年1月1日-2020年10月1日的数, 一定在[20000101, 20201001]之间, 只枚举需要判断是否是合法天数即可
- **结论2: **星期用%7判断就行
#include <iostream>
#include <string>
using namespace std;
int months[]={
-1,31,28,31,30,31,30,31,31,30,31,30,31};
void IsRun(int year) {
if(year%4==0&&year%100!=0||year%400==0) months[2]=29;else months[2]=28;}
bool is_Year(int Y,int M, int D) {
IsRun(Y);
if(M<1||M>12) return false;
if(D<1||D>months[M]) return false;
return true;
}
int