叠Buff
大一小白第一次参加篮球杯,本人太菜了,大概只有五十分左右,只能做出部分简单题
A.移动距离
题目链接:P12130 [蓝桥杯 2025 省 B] 移动距离 - 洛谷
纯数学题,刚看到的时候没有什么思路,把后面简单一点的做了才回来看这题,感觉应该要先一直往右走,在沿着圆弧走,还好猜对了,应该可以有严谨的数学证明的,不过我太菜了感觉好复杂.。最后答案应该是1576
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cout << int(sqrt(666 * 666 + 233 * 233) * (1 + atan(666.0 / 233))) << endl;
return 0;
}
B.客流量上限
题目链接:P12131 [蓝桥杯 2025 省 B] 客流量上限 - 洛谷
我太菜了,还不会,答案是
C.可分解的正整数
题目链接:P12132 [蓝桥杯 2025 省 B] 可分解的正整数 - 洛谷
开始脑子瓦特了,想着一个数是合数就可以,然后发现是质数好像也可以,最后敲了一坨,发现合数和质数。。。不就是大于1的正整数吗。本题判断每个数是否为1即可,因为大于1的任意数都可以表示成 ..., 0, 1, ..., 而1只能表示成0,1,是不合法的。
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int n, ans = 0;
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 0; i < n; i ++ )
{
int x;
cin >> x;
if (x != 1) ans ++ ;
}
cout << ans << endl;
return 0;
}
D.产值调整
题目链接:P12133 [蓝桥杯 2025 省 B] 产值调整 - 洛谷
观察题目数据范围后发现都是1e9级别的,太大了,简单模拟几个样例后发现三个数在不断地趋近,操作次数到某一定量时三个数会变得相同,接下来继续操作是没有意义的,并且操作次数不会太多,所以不断模拟操作即可,在三者相同或k为0时退出循环
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
void solve()
{
int a, b, c, k;
cin >> a >> b >> c >> k;
while ((a != b || a != c || b != c) && k)
{
k -- ;
int x = a, y = b, z = c;
a = (y + z) / 2;
b = (x + z) / 2;
c = (x + y) / 2;
}
cout << a << " " << b << " " << c << endl;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
int t = 1;
cin >> t;
while (t -- ) solve();
return 0;
}
E.画展布置
题目链接:P12134 [蓝桥杯 2025 省 B] 画展布置 - 洛谷
容易发现我们需要先将数组a进行排序,因为在选择三个及三个以上画作时,假设三个画作xyz的艺术价值大小为x < y > z, 协调性为y - x + y - z, 而把xyz排序为x < z < y后,协调性变为z - x + y - z,与前者相比差异在于y - x 和 z - x,而y > z, 故y - x > z - x, 所以排序后的协调性是小于乱序的协调性的。所以将数组a排序后比较每个连续区间长度为m的协调性,取消最小值即可,因为, 所以求一段区间[l, r]的协调性可简化为
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long LL;
const int N = 100010;
int n, m;
LL res = 1e18;
LL a[N];
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1; i <= n; i ++ ) cin >> a[i], a[i] *= a[i];
sort(a + 1, a + n + 1);
for (int l = 1, r = m; r <= n; l ++ , r ++ ) res = min(res, a[r] - a[l]);
cout << res << endl;
return 0;
}
F.水质检测
题目链接:P12135 [蓝桥杯 2025 省 B] 水质检测 - 洛谷
我太菜了,赛时没做对,贪心部分有问题,导致我的结果比正确答案可能会小一点,不过应该也能骗点分,这题做法应该有很多,参考苯环大佬的题解(题解:P12135 [蓝桥杯 2025 省 B] 水质检测 - 洛谷专栏,膜拜大佬),我差不多理解了,将每一列分成三类,从左往右依次考虑。若当前列为第一类,上一个状态为第二类,在第一行和第二行铺设所需要的个数是相同的,但是此时在第二行铺设一定更优,因为可以将当前状态变为第三类。其他情况较易理解
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
int ans, last = -1, state;
// state: 1 2 3
// # . #
// . # #
string a, b;
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> a >> b;
for (int i = 0; i < a.size(); i ++ )
{
if (a[i] == '.' && b[i] == '.') continue;
if (last != -1) ans += i - last - 1;
if (a[i] == '#' && b[i] == '.')
{
if (state == 2)
{
ans ++ ;
state = 3;
}
else state = 1;
}
else if (a[i] == '.' && b[i] == '#')
{
if (state == 1)
{
ans ++ ;
state = 3;
}
else state = 2;
}
else state = 3;
last = i;
}
cout << ans << endl;
return 0;
}
G.生产车间
题目链接:P12136 [蓝桥杯 2025 省 B] 生产车间 - 洛谷
我太菜了,直接输出的w[1],赛时没做出来,没想清楚如何枚举每个节点可能的情况,原来可以直接开个set,合法的直接insert就行了,开个vector<bool>应该也是一样的,可能时间效率会好一点,不过注意set会自动去重并排序,所以在枚举每种情况时,当x+y>w[u]时直接break而不是contiunue,当前值都已经比较大了后面的只会更大。g[u].szie()==1&&u!=1判断该节点是否为叶子节点,可能的情况只有两种即选或不选{0, w[u]}。该代码可以勉强大部分测试点,但是感觉没什么测试点可以卡的太死的,时间复杂度最坏情况是 的,可以考虑用bitset优化不过本人太菜了不太会
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N = 1010;
int n;
int w[N];
vector<int> g[N];
set<int> dfs(int u, int p)
{
if (g[u].size() == 1 && u != 1) return {0, w[u]};
set<int> s{0};
for (auto v : g[u])
{
if (v == p) continue;
auto t = dfs(v, u);
auto st = s;
for (auto x : st)
for (auto y : t)
{
if (x + y > w[u]) break;
s.insert(x + y);
}
}
return s;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> w[i];
for (int i = 1; i < n; i ++ )
{
int a, b;
cin >> a >> b;
g[a].push_back(b);
g[b].push_back(a);
}
auto t = dfs(1, 0);
cout << *t.rbegin() << endl;
return 0;
}
bitset优化版(感觉大差不差)
// G.生产车间
// bitset
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
const int N = 1010;
int n;
int w[N];
vector<int> g[N];
bitset<N> dfs(int u, int p)
{
bitset<N> dp;
dp[0] = 1;
if (g[u].size() == 1 && u != 1)
{
dp[w[u]] = 1;
return dp;
}
for (auto v : g[u])
{
if (v == p) continue;
auto t = dfs(v, u);
auto s = dp;
for (int i = 0; i <= w[u]; i ++ )
for (int j = 0; j <= w[v]; j ++ )
{
if (i + j > w[u]) break;
if (s[i] && t[j]) dp[i + j] = 1;
}
}
return dp;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> w[i];
for (int i = 1; i < n; i ++ )
{
int a, b;
cin >> a >> b;
g[a].push_back(b);
g[b].push_back(a);
}
auto ans = dfs(1, 0);
for (int i = w[1]; i >= 0; i -- )
if (ans[i])
{
cout << i << endl;
break;
}
return 0;
}
H.装修报价
题目链接:P12137 [蓝桥杯 2025 省 B] 装修报价 - 洛谷
我太菜了,还不会,哪怕做了一些位运算的题,感觉应该要按位考虑,但是完全想不出来正确解法,下面是赛时做的dfs暴力解法,大概有30%的分
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long LL;
const int N = 100010;
const int mod = 1e9 + 7;
int n;
LL ans;
LL a[N];
int op[N];
void dfs(int u)
{
if (u == n)
{
LL t = a[1];
for (int i = 1; i < n; i ++ )
{
if (op[i] != 3 && op[i + 1] == 3)
{
LL res = a[i + 1];
int j = i + 1;
while (j + 1 < n && op[j + 1] == 3) res ^= a[ ++ j];
if (op[i] == 1) t += res;
else t -= res;
i = j;
continue;
}
else
{
if (op[i] == 1) t += a[i + 1];
else if (op[i] == 2) t -= a[i + 1];
else t ^= a[i + 1];
}
}
ans = (ans + t) % mod;
return;
}
for (int i = 1; i <= 3; i ++ )
{
op[u] = i;
dfs(u + 1);
}
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> a[i];
dfs(1);
cout << ans << endl;
return 0;
}
正解:贡献法,位运算题目的另外一种常用方法,难怪按位考虑想不出来。 当我们观察样例说明时,容易发现有很多数是相反数,从而相互抵消,而返计算这种相反数是没有意义的,我们考虑何时会产生这种相反数,在一般加减法运算中,将所有的加法换为减法,减法换位加法,就得到了原式的相反数。
在本题中按位异或的优先级大于加减法。因此我们可以将一段连续的异或运算看成一个数字,从而只剩下加法和减法了,而由于是在两个数之间插入运算符,所以第一个数的前面永远可以看成是加法,显然地,只有前缀异或才对答案有贡献,我们只用考虑前缀异或的结果。
特别的,假设前缀异或长度为i,则在第i+1个位置时,只能时+或-,否则前缀异或长度就变为了i+1,从第i+2个位置开始每个位置都有三种情况,假设前缀异或的值为res,那么该情况对答案的贡献就是。
#include <bits/stdc++.h>
#define endl '\n'
using namespace std;
typedef long long LL;
const int N = 100010;
const int mod = 1e9 + 7;
int n;
LL ans, res, t = 1;
LL a[N];
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i ++ )
{
cin >> a[i];
res ^= a[i];
}
// 此时res为所有数异或的结果
ans = res;
res ^= a[n]; // 前n-1个数异或的结果
// 从前n-1个数开始考虑,不需要每次都使用快速幂计算3的幂次,保证了n-(i-1)>=0, 当然特判一下也可以
for (int i = n - 1; i >= 0; i -- )
{
ans = (ans + res * 2 * t % mod) % mod;
t = (t * 3) % mod;
res ^= a[i];
}
cout << ans << endl;
return 0;
}
总结
我还是太菜了,大佬勿喷
7226

被折叠的 条评论
为什么被折叠?



