做对了1 2 3 4 8题,共得60分
其中第9题运行超时,得10分
用时两个半小时
1、5 进制转换
2 日期
3 简单数学
4 简单数学,找规律
6 二维前缀和,双指针
7 未看
8 简单搜索
9 dfs+dp+剪枝(记忆型dfs)
10 未看
九进制转十进制
问题描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
九进制正整数
(
2022
)
9
(2022)_9
(2022)9 转换成十进制等于多少?
很简单的一题
#include <iostream>
using namespace std;
int main()
{
// 请在此输入您的代码
cout << 1478;
return 0;
}
顺子日期
问题描述
本题为填空题,只需要算出结果后,在代码中使用输出语句将所填结果输出即可。
小明特别喜欢顺子。顺子指的就是连续的三个数字:123、456 等。顺子日期指的就是在日期的 yyyymmdd 表示法中,存在任意连续的三位数是一个顺子的日期。例如 20220123 就是一个顺子日期,因为它出现了一个顺子:123; 而 20221023 则不是一个顺子日期,它一个顺子也没有。小明想知道在整个 2022 年份中,一共有多少个顺子日期?
1230
1231
1123
1012
0120,0121,0122,0123…(10个)
#include <iostream>
using namespace std;
int main()
{
// 请在此输入您的代码
cout << 14;
return 0;
}
刷题统计
问题描述
小明决定从下周一开始努力刷题准备蓝桥杯竞赛。他计划周一至周五每天做a道题目, 周六和周日每天做b道题目。请你帮小明计算, 按照计划他将在第几天实现做题数大于等于n题?
输入格式
输入一行包含三个整数 a,b和 n.
输出格式
输出一个整数代表天数。
样例输入
10 20 99
样例输出
8
评测用例规模与约定
对于 50 50% 50 的评测用例, 1 ≤ a , b , n ≤ 1 0 6 1≤a,b,n≤10^6 1≤a,b,n≤106
对于 100 100% 100 的评测用例, 1 ≤ a , b , n ≤ 1 0 18 1≤a,b,n≤10^{18} 1≤a,b,n≤1018
#include<iostream>
using namespace std;
typedef long long ll;
ll a, b, n;
int main()
{
cin >> a >> b >> n;
ll week = a * 5 + b * 2;
ll t = n / week;//t个完整的周
ll sum = t * week;//实际t周做的量
t *= 7;
for (int i = 1; i <= 7; i ++)
{
if (sum < n)
{
if (i <= 5) sum += a;//周一到五
else sum += b;//周末
t ++;//加一天
}
}
cout << t;
return 0;
}
先直接算出需要多少个完整的一周
修剪灌木
问题描述
爱丽丝要完成一项修剪灌木的工作。
有N棵灌木整齐的从左到右排成一排。爱丽丝在每天傍晩会修剪一棵灌 木, 让灌木的高度变为 0 厘米。爱丽丝修剪灌木的顺序是从最左侧的灌木开始, 每天向右修剪一棵灌木。当修剪了最右侧的灌木后, 她会调转方向, 下一天开 始向左修剪灌木。直到修剪了最左的灌木后再次调转方向。然后如此循环往复。
灌木每天从早上到傍晩会长高 1 厘米, 而其余时间不会长高。在第一天的 早晨, 所有灌木的高度都是 0 厘米。爱丽丝想知道每棵灌木最高长到多高。
输入格式
一个正整数 NN, 含义如题面所述。
输出格式
输出 NN 行, 每行一个整数, 第 ii 行表示从左到右第 ii 棵树最高能长到多高。
样例输入
3
样例输出
4
2
4
评测用例规模与约定
对于 30 30% 30 的数据, N ≤ 10 N≤10 N≤10.
对于 100 100% 100的数据, 1 < N ≤ 10000 1<N≤10000 1<N≤10000
#include<iostream>
using namespace std;
int n;
int h[10010];
int main()
{
cin >> n;
int t = (n+1)/2;
for (int i = 1; i <= t; i ++)
{
h[i] = (n-i) * 2;
}
for (int i = t + 1; i <= n; i ++)
h[i] = h[n-i+1];
for (int i = 1; i <= n; i ++)
cout << h[i] << endl;
return 0;
}
找规律
比如是4棵树,砍树顺序如下:(每一列对应一棵树)
1 2 3 4
7 6 5 **
**8 9 10
第一次砍第1棵树是(1),第二次砍是(7),在这一段时间里第1棵树可以长到6
第一次砍第2棵树是(2),第二次砍是(6),在这一段时间里第1棵树可以长到4
再找规律可以发现每一棵树的最高高度是对称的
第3棵树最高4,第4棵树最高6
比如是5棵树,砍树顺序如下:(每一列对应一棵树)
1 2 3 4 5
9 8 7 6 **
**10 11 12 13
第一次砍第1棵树是(1),第二次砍是(9),在这一段时间里第1棵树可以长到8
第一次砍第2棵树是(2),第二次砍是(8),在这一段时间里第1棵树可以长到6
再找规律可以发现每一棵树的最高高度是对称的
第3棵树最高4,第4棵树最高6,第5棵树最高8
就可以找出规律:在前一半树中
第i棵树最高:(n-i)*2;
X 进制减法
问题描述
进制规定了数字在数位上逢几进一。
X 进制是一种很神奇的进制, 因为其每一数位的进制并不固定!例如说某 种 X 进制数, 最低数位为二进制, 第二数位为十进制, 第三数位为八进制, 则 X 进制数 321 转换为十进制数为 65 。
现在有两个 X 进制表示的整数 A 和 B, 但是其具体每一数位的进制还不确 定, 只知道 A 和 B 是同一进制规则, 且每一数位最高为 N 进制, 最低为二进 制。请你算出 A−B 的结果最小可能是多少。
请注意, 你需要保证 A 和 B 在 X 进制下都是合法的, 即每一数位上的数 字要小于其进制。
输入格式
第一行一个正整数 N, 含义如题面所述。
第二行一个正整数 Ma, 表示 X 进制数 A 的位数。
第三行 Ma 个用空格分开的整数, 表示 X 进制数 A 按从高位到低位顺序各 个数位上的数字在十进制下的表示。
第四行一个正整数 Mb, 表示 X 进制数 B 的位数。
第五行 Mb个用空格分开的整数, 表示 X 进制数 B 按从高位到低位顺序各 个数位上的数字在十进制下的表示。
请注意, 输入中的所有数字都是十进制的。
输出格式
输出一行一个整数, 表示 X 进制数 A−B 的结果的最小可能值转换为十进 制后再模 1000000007 的结果。
样例输入
11
3
10 4 0
3
1 2 0
样例输出
94
样例说明
当进制为: 最低位 2 进制, 第二数位 5 进制, 第三数位 11 进制时, 减法 得到的差最小。此时 A 在十进制下是 108,B在十进制下是 14 , 差值是 94。
#include<iostream>
#include<cstdio>
typedef long long ll;
using namespace std;
const int N = 100010;
const int MOD = 1000000007;
int n, ma,mb;
int a[N], b[N];
int mx[N];
int ans[N];
int main()
{
cin >> n;
cin >> ma;
for (int i = 0; i < ma; i ++) cin >> a[i];
cin >> mb;
for (int i = ma-mb; i < ma; i ++) cin >> b[i];
for (int i = 0; i < ma; i ++)
{
mx[i] = max(a[i],b[i]) + 1; //当前最低进制
if (mx[i] < 2) mx[i] = 2;
}
for (int i = ma-1; i >= 0; i --)
{
if (a[i] >= b[i]) ans[i] = a[i] - b[i];
else{
a[i] += mx[i];
a[i+1] --;//借一位
ans[i] = a[i] - b[i];
}
}
int res = ans[0];
for (int i = 1; i < ma; i ++)
res = (((ll)mx[i] * res)%MOD + (ll)ans[i]) %MOD;
cout << res;
return 0;
}
减法那块想错了,想着可能减法中,a>b就要借位。。其实不用,减法都可以直接减得了
#include<iostream>
#include<cstdio>
typedef long long ll;
using namespace std;
const int N = 100010;
const ll MOD = 1000000007;
int n, ma,mb;
int a[N], b[N];
int mx[N];
ll ans[N];
int main()
{
cin >> n;
cin >> ma;
for (int i = 0; i < ma; i ++) cin >> a[i];
cin >> mb;
for (int i = ma-mb; i < ma; i ++) cin >> b[i];
for (int i = 0; i < ma; i ++)
{
mx[i] = max(a[i],b[i]) + 1; //当前最低进制
if (mx[i] < 2) mx[i] = 2;
}
for (int i = ma-1; i >= 0; i --)
{
ans[i] = a[i] - b[i];
// else{
// a[i] += mx[i];
// a[i+1] --;//借一位
// ans[i] = a[i] - b[i];
// }
}
ll res = ans[0];
for (int i = 1; i < ma; i ++)
res = (((ll)mx[i] * res)%MOD + (ll)ans[i]) %MOD;
cout << res;
return 0;
}
统计子矩阵
问题描述
给定一个 N×M 的矩阵 A, 请你统计有多少个子矩阵 (最小 1×1, 最大 N×M)满足子矩阵中所有数的和不超过给定的整数 K ?
输入格式
第一行包含三个整数 N,M,K.
之后 N 行每行包含 M 个整数, 代表矩阵 A.
输出格式
一个整数代表答案。
样例输入
3 4 10
1 2 3 4
5 6 7 8
9 10 11 12
样例输出
19
#include<iostream>
using namespace std;
typedef long long ll;
const int N = 55;
int n, m, k;
int a[N][N];
ll f[N][N];
int main()
{
cin >> n>> m >> k;
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j ++)
cin >> a[i][j];
for (int j = 1; j <= m; j ++)
for (int i = 1; i <= n; i ++)
f[i][j] = f[i-1][j] + a[i][j];
int res = 0;
for (int i = 1; i <= n; i ++)
for (int j = i; j <= n; j ++)
{
for (int l = 1,r = 1;l <= m; l ++)
{
ll sum = f[j][l] - f[i-1][l];
while (r <= m && sum <= k)
{
r ++;
sum += f[j][r] - f[i-1][r];
}
if (r > l)
res += (r - l);
}
}
cout << res;
return 0;
}
主要是 ll sum = f[j][l] - f[i-1][l];
写错了,他计算的值是要一直用下去的。。
并且还有很多小错误,,,,
最后一个错误是看错了N的数据范围。。。
- 改过的
#include<iostream>
using namespace std;
typedef long long ll;
const int N = 505;
int n, m;
ll k;
int a[N][N];
int f[N][N];
int main()
{
cin >> n>> m >> k;
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j ++)
cin >> a[i][j];
for (int j = 1; j <= m; j ++)
for (int i = 1; i <= n; i ++)
f[i][j] = f[i-1][j] + a[i][j];
ll res = 0;
for (int i = 1; i <= n; i ++)
for (int j = i; j <= n; j ++)
{
ll sum = f[j][1] - f[i-1][1];
for (int l = 1,r = 1;l <= m; l ++)
{
while (r <= m && sum <= k)
{
r ++;
sum += f[j][r] - f[i-1][r];
}
res += (r - l);
sum -= f[j][l] - f[i-1][l];
}
}
cout << res;
return 0;
}
扫雷
题目描述
在一个 n 行 m 列的方格图上有一些位置有地雷,另外一些位置为空。
请为每个空位置标一个整数,表示周围八个相邻的方格中有多少个地雷。
输入描述
输入的第一行包含两个整数 n,m。
第 2 行到第 n+1 行每行包含 m 个整数,相邻整数之间用一个空格分隔。如果对应的整数为 0,表示这一格没有地雷。如果对应的整数为 1,表示这一格有地雷。
其中,1≤n,m≤100 分钟后还是在当天。
输出描述
输出 n 行,每行 m 个整数,相邻整数之间用空格分隔。
对于没有地雷的方格,输出这格周围的地雷数量。对于有地雷的方格,输出 9。
输入输出样例
示例 1
输入
3 4
0 1 0 0
1 0 1 0
0 0 1 0
输出
2 9 2 1
9 4 9 2
1 3 9 2
#include<iostream>
using namespace std;
int n, m;
int a[105][105];
int dx[10] = {0,-1,-1,-1,0,1,1,1};
int dy[10] = {-1,-1,0,1,1,1,0,-1};
int main()
{
cin >> n >> m;
for (int i = 1; i <= n; i ++)
for (int j = 1; j <= m; j ++)
{
int q;
cin >> q;
if (q == 1) a[i][j] = 9;
else a[i][j] = 0;
}
for (int i = 1; i <= n; i ++)
for (int j = 1;j <= m; j ++)
{
if (a[i][j] == 9) continue;
for (int k = 0; k < 8; k ++)
{
if (a[i+dx[k]][j+dy[k]] == 9)
a[i][j] ++;
}
}
for (int i = 1; i <= n; i ++)
{
for (int j = 1;j <= m; j ++)
cout << a[i][j] << ' ';
cout << '\n';
}
return 0;
}
李白打酒加强版
问题描述
话说大诗人李白, 一生好饮。幸好他从不开车。
一天, 他提着酒显, 从家里出来, 酒显中有酒 2 斗。他边走边唱:
无事街上走,提显去打酒。 逢店加一倍, 遇花喝一斗。
这一路上, 他一共遇到店 NN 次, 遇到花 MM 次。已知最后一次遇到的是花, 他正好把酒喝光了。
请你计算李白这一路遇到店和花的顺序, 有多少种不同的可能?
注意: 显里没酒 ( 0 斗) 时遇店是合法的, 加倍后还是没酒; 但是没酒时遇 花是不合法的。
输入格式
第一行包含两个整数 N 和 M.
输出格式
输出一个整数表示答案。由于答案可能很大,输出模 1000000007 的结果.
样例输入
5 10
样例输出
14
- 暴力做法,只用了dfs(拿了10分)
#include<iostream>
using namespace std;
const int MOD = 1000000007;
int n, m;
int res;
void dfs(int x)
{
if (x == 1 && n == 0 && m == 1)
{
res = res%MOD + 1;
return;
}//else if (x < 2) return;
for (int i = 0; i < 2; i ++)
{
if (i == 0 && n > 0 && x > 0)
{
n --;
dfs(x*2);
n ++;
}else if (i == 1 && m > 1)
{
if (x == 0) return; //不合法
else
{
m --;
dfs(x-1);
m ++;
}
}
}
return ;
}
int main()
{
cin >> n >> m;
dfs(2);
cout << res%MOD;
return 0;
}
- 看了别人的题解:dfs+dp(记忆型搜索)
#include<iostream>
#include<cstring>
using namespace std;
const int MOD = 1000000007;
int n, m;
int res;
int dp[110][110][110];
int dfs(int x, int nn, int mm)
{
if (x <0 || nn < 0 || mm < 0) return 0;
if (x > mm) return 0;
if (x == 1 && nn == 0 && mm == 1)
return 1;
if(dp[x][nn][mm] != -1) return dp[x][nn][mm];
else return dp[x][nn][mm] = (dfs(x*2, nn-1, mm)+dfs(x-1,nn,mm-1)) % MOD;
}
int main()
{
cin >> n >> m;
memset(dp, -1, sizeof dp);
cout << dfs(2, n, m);
return 0;
}