【洛谷】P8713 [蓝桥杯 2020 省 A2] 填空问题 的题解
传送门
A:门牌制作
思路
这题没什么好说的,就直接暴力枚举就行。
代码
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
namespace fastIO {
inline int read() {
register int x = 0, f = 1;
register char c = getchar();
while (c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
inline void write(int x) {
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
return;
}
}
using namespace fastIO;
int main() {
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
int cnt = 0;
for(int i = 1; i <= 2020; i ++) {
int temp = i;
while(temp) {
if(temp % 10 == 2) cnt ++;
temp /= 10;
}
}
write(cnt);
return 0;
}
算出来答案为: 624 624 624。
B:既约分数
思路
暴力枚举枚举出分子和分母,然后判断是不是既约分数即可。
代码
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
namespace fastIO {
inline int read() {
register int x = 0, f = 1;
register char c = getchar();
while (c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
inline void write(int x) {
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
return;
}
}
using namespace fastIO;
int main() {
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
int cnt = 0;
for(int i = 1; i <= 2020; i ++) {
for(int j = 1; j <= 2020; j ++) {
if(__gcd(i, j) == 1) {
cnt ++;
}
}
}
write(cnt);
return 0;
}
算出来答案为: 2481215 2481215 2481215。
C:蛇形填数
思路
从右上角到左下角,再从左下角到右上角, c n t cnt cnt 记录要填的数,数组里存的数字表示该位置应该填的数, u u u 代表横坐标, d d d 代表纵坐标。
横坐标降为 1 1 1 时,填完数后纵坐标 + 1 +1 +1。
纵坐标降为 1 1 1 时,填完数后横坐标 + 1 +1 +1。
提醒一点:求的是第 20 20 20 行第 20 20 20 列,这可不是 20 × 20 20 \times 20 20×20 的格子数就可以模拟完的,数组得开大点。
代码
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
namespace fastIO {
inline int read() {
register int x = 0, f = 1;
register char c = getchar();
while (c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
inline void write(int x) {
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
return;
}
}
using namespace fastIO;
int main() {
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
int cnt = 0, x = 1, y = 1, a[105][105];
memset(a, 0, sizeof(a));
a[x][y] = ++ cnt;
while(!a[20][20]) {
x ++;
while(x != 1) {
a[x --][y ++] = ++ cnt;
}
a[x][y] = ++ cnt;
y ++;
while(y != 1) {
a[x ++][y --] = ++ cnt;
}
a[x][y] = ++ cnt;
}
write(a[20][20]);
return 0;
}
算出来答案为: 761 761 761。
D:七段码
思路
-
因为 a b c d e f g abcdefg abcdefg 每条管(或者叫边)只有发光和不发光两种状态,所以可以状压,去用一个 7 7 7 位的 01 01 01 串表示该七段码管的状态。
-
枚举七段码管所有可能出现的状态。
-
DFS 去判断每个状态里发光的边是否连通即可。
代码
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
namespace fastIO {
inline int read() {
register int x = 0, f = 1;
register char c = getchar();
while (c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
inline void write(int x) {
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
return;
}
}
using namespace fastIO;
bool g[8][8], vis[8], vis1[8];
int res = 0, ans, cnt;
string s;
string Binary(int x) {
string s = "";
while(x) {
if(x % 2 == 0) s = '0' + s;
else s = '1' + s;
x /= 2;
}
return s;
}
void dfs(int x) {
if(cnt == ans) {
res++;
return;
}
for(int i = 1; i <= 7; i ++) {
if(vis1[i] || !g[x][i] || !vis[i]) continue;
cnt++;
vis1[i] = true;
dfs(i);
}
}
void check(int i) {
for(int i = 1; i <= 7; i++) vis[i] = vis1[i] = false;
s = Binary(i);
ans = 0;
for(int i = s.length() - 1; i >= 0; i--)
if(s[i] == '1') vis[s.length()-i] = true,ans++;
for(int i = 1; i <= 7; i++)
if(vis[i]) {
vis1[i] = true;
cnt = 1;
dfs(i);
return;
}
}
int main() {
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
memset(g, false, sizeof(g));
g[1][2] = g[1][6] = 1;
g[2][1] = g[2][7] = g[2][3] = 1;
g[3][2] = g[3][4] = g[3][7] = 1;
g[4][5] = g[4][3] = 1;
g[5][6] = g[5][7] = g[5][4] = 1;
g[6][1] = g[6][7] = g[6][5] = 1;
g[7][2] = g[7][3] = g[7][5] = g[7][6] = 1;
for(int i = 1; i < (1<<7); i++)
check(i);
write(res);
return 0;
}
算出来答案为: 80 80 80。
E:平面分割
思路
看到这个题,首先会发现是无法用程序去模拟分割的,所以肯定有一定的规律。
规律都是由小到大得出来的,所以我们先从一条直线看起:
如果只有直线,要想构造的分割块最多,那么新添加的直线就要与之前所有的直线相交,而且不能经过之前的直线所形成的交点。
所以规律:
平面上有 0 0 0 条直线,有 1 1 1 个部分。
平面上有 1 1 1 条直线,可以划分出 1 + 1 1+1 1+1 个部分。
平面上有 2 2 2 条直线,可以划分出 1 + 1 + 2 1+1+2 1+1+2 个部分。
平面上有 3 3 3 条直线,可以划分出 1 + 1 + 2 + 3 1+1+2+3 1+1+2+3 个部分。
然后就不难想到平面上有 n n n 条直线时,其可划分出的部分最多为 z ( n ) = n × ( n + 1 ) ÷ 2 + 1 z(n) = n \times (n + 1) \div 2 + 1 z(n)=n×(n+1)÷2+1。
那如果加上圆呢?
首先必须记住一点,这个圆的大小是任意的,这也是直线和圆能分开考虑的关键。
打个表找一下规律:
可以看到 f ( n , m ) = f ( n , m − 1 ) + 2 × ( n + m − 1 ) f(n , m) = f(n, m - 1) + 2 \times (n + m - 1) f(n,m)=f(n,m−1)+2×(n+m−1),其中 f ( n , m ) f(n, m) f(n,m) 表示 n n n 条直线, m m m 个圆时的分割块个数。
代码
#include <bits/stdc++.h>
#define endl "\n"
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
namespace fastIO {
inline int read() {
register int x = 0, f = 1;
register char c = getchar();
while (c < '0' || c > '9') {
if(c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
inline void write(int x) {
if(x < 0) putchar('-'), x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
return;
}
}
using namespace fastIO;
int main() {
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
int num = 20 * 21 / 2 + 1;
for(int i = 1; i <= 20; i ++) {
num += 2 * (i + 20 - 1);
}
write(num);
return 0;
}
算出来答案为: 1391 1391 1391。
AC代码
#include<iostream>
using namespace std;
int main() {
string ans [] = {
"624",
"2481215",
"761",
"80",
"1391",
};
char T;
cin >> T;
cout << ans[T - 'A'] << endl;
return 0;
}