第一题
本题非常简单 但多次ac不过 注意数据范围 在暴力的基础上要注意优化算法 非数据量特别小的题肯定会卡一部分超时 多注意语句是否有遗漏 比赛不会直接出结果 不方便找bug 本题在ac过程中多次缺少一些语句 思路简单 代码残缺
#include<iostream>
using namespace std;
typedef long long ll;
ll a, b, goal;
int main(){
cin >> a >> b >> goal;
ll sum = a * 5 + b * 2;
ll count = goal / sum;//先将刷题数降到一周以内 减少循环次数 否则会超时
goal = goal % sum;
int ans = 0;//本周需要刷多少天
if(goal % sum != 0)
for(int i = 1; ; i = i % 7 + 1){
if(i <= 5)
goal -= a;
else
goal -= b;
ans ++;
if(goal <= 0)
break;
}
cout << ans + count * 7;
return 0;
}
第二题
遇到该类模拟题 建议直接推导公式 模拟几种情况 可以得出 N棵左边的树最高可以长到(n - i)* 2
右边的树最高可以长到(i - 1) * 2 注意答案格式 会换行输出还是空格输出 千万注意
#include<iostream>
using namespace std;
int main(){
int n;
cin >> n;
for(int i = 1; i <= n; i ++){
if(i <= n / 2)
cout << (n - i) * 2 << endl;
else
cout << (i - 1) * 2 << endl;
}
return 0;
}
第三题
题意理解起来都费劲
321 ---> 65 的转变过程
首先题目解释了进制的含义 逢几进一 2 可以看作个位二进制下逢2进1进上来的 因此 这个2的十进制表示就是2 * 2 = 4 3可以看作第二数位逢十进一进上来的 3 = 3 * 10 * 2 = 60 而个位数1 就代表1即可 总和为65
题解 针对蓝桥杯此题存在两道特殊测试点 A > B 但是ma < mb 即A的位数少于B 因此权值累加的步骤下要取二者长度较大的一个
注意读取数据时的形式 可以借鉴 省得再转置数组 或 从尾部下标向前导
简单来说不难 要注意的点比较多 一是注意计算每一步都要取模 说不定哪个测试数据就爆了
/*
简便的一种方法 直接计算每一位的差值 累加求和
*/
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
const int N = 1e7;
const int mod = 1000000007;
int A[N], B[N];
ll ans = 0;
int main(){
int n;
cin >> n;
//从低位到高位正好与下标对应
int ma, mb;
cin >> ma;
for(int i = ma; i >= 1; i --)
scanf("%d", &A[i]);
cin >> mb;
for(int i = mb; i >= 1; i --)
scanf("%d", &B[i]);
//位权用cnt进行累加记录
ll cnt = 1;
int size = max(ma, mb);
for(int i = 1; i <= size; i ++){
//直接计算每一位的差值
ans += (((A[i] - B[i]) * cnt) % mod);
ans %= mod;
cnt = (cnt * max(max(A[i], B[i]) + 1, 2)) % mod;
}
if(ans < 0)
ans = (ans + mod) % mod;
cout << ans;
return 0;
}
/*
较麻烦的一种方法 首先计算每位的位权 再分别计算出A B(取模后的值) 最后进行运算
*/
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
const int N = 1e7;
const int mod = 1000000007;
int A[N], B[N];
ll ans = 0, weight[N], a, b;
int main(){
int n;
cin >> n;
//从低位到高位正好与下标对应
int ma, mb;
cin >> ma;
for(int i = ma; i >= 1; i --)
scanf("%d", &A[i]);
cin >> mb;
for(int i = mb; i >= 1; i --)
scanf("%d", &B[i]);
//位权从最低位开始 weight[1]存 1
ll cnt = 1;
weight[1] = 1;//j 最小到 1 最高位位权计算时不需要包含它本身的进制 无需到 0
int size = max(ma, mb);
for(int i = 2; i <= size; i ++){
//计算次位的进制
cnt = max(max(A[i - 1], B[i - 1]) + 1, 2);
//前缀和思想存储权值 避免循环
weight[i] = (cnt * weight[i - 1]) % mod;
}
//计算 A
for(int i = 1; i <= ma; i ++){
a += (A[i] * weight[i]);
a %= mod;
}
//计算 B
for(int i = 1; i <= mb; i ++){
b += (B[i] * weight[i]);
b %= mod;
}
//避免出现负数 a取模后小于b
ans = (a - b + mod) % mod;
cout << ans;
return 0;
}
第四题 统计子矩阵
思路 本来想的是深搜枚举所有子矩阵 后来发现这根本没办法搜
半正解是二维前缀和 四重循环枚举子矩阵的和
正解是一维前缀和+滑动双指针 理解不了
/*
披着深搜的皮 实际应该不能用深搜模拟出来 前缀和登场
*/
#include<iostream>
using namespace std;
const int N = 1000;
typedef long long ll;
int n, m, K, ans;
int num[N][N], sum[N][N];
int main(){
scanf("%d %d %d", &n, &m, &K);
for(int i = 1; i <= n; i ++){
for(int j = 1; j <= m; j ++){
scanf("%d", &num[i][j]);
sum[i][j] = sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1] + num[i][j];
}
}
ll all = 0;
for(int i = 1; i <= n; i ++){
for(int k = i; k <= n; k ++){
for(int j = 1; j <= m; j ++){
for(int l = j; l <= m; l ++){
all = sum[k][l] - sum[i - 1][l] - sum[k][j - 1] + sum[i - 1][j - 1];
if(all <= K)
ans ++;
else
break;
}
}
}
}
cout << ans;
return 0;
}
能拿点是点