mirror of
https://gitcode.com/Zengtudor/alg2025.git
synced 2025-10-26 10:02:47 +00:00
feat: 添加两道编程题解 P7556 和 P9124
添加两道编程竞赛题解: 1. P7556.cpp 实现集合元素组合验证逻辑 2. P9124.cpp 使用二分查找解决优化问题,处理大数运算防止溢出
This commit is contained in:
parent
32de376783
commit
88b33ff757
115
src/10/19/P9124.cpp
Normal file
115
src/10/19/P9124.cpp
Normal file
@ -0,0 +1,115 @@
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <iostream>
|
||||
#include <istream>
|
||||
// 使用 long long 防止溢出,特别是 c_i 可以达到 2*10^18
|
||||
using ll = long long;
|
||||
|
||||
#define sl static inline
|
||||
|
||||
const ll maxn = 100 + 5;
|
||||
ll T, n;
|
||||
// tc, tm 定义为 long long 以匹配 c_i 的数量级,防止计算中溢出
|
||||
ll tc, tm;
|
||||
ll a[maxn], b[maxn], c[maxn];
|
||||
|
||||
// 检查总花费 S 是否可行
|
||||
// 替换了原来错误的 checkall 函数
|
||||
sl bool checkall(ll S) {
|
||||
// 设 cookie 制作时间减少 x,则 muffin 减少 S-x
|
||||
// 我们需要寻找是否存在一个 x 满足所有约束
|
||||
|
||||
// 约束1: x 必须在花费和时间限制内
|
||||
// x >= 0, S-x >= 0 => 0 <= x <= S
|
||||
// tc - x >= 1 => x <= tc - 1
|
||||
// tm - (S-x) >= 1 => x >= S - tm + 1
|
||||
ll lower_x = std::max(0LL, S - tm + 1);
|
||||
ll upper_x = std::min(S, tc - 1);
|
||||
|
||||
// 如果初始约束已经无解,则该 S 不可行
|
||||
if (lower_x > upper_x) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 约束2: 满足所有朋友的时间要求
|
||||
// a_i * (tc - x) + b_i * (tm - (S-x)) <= c_i
|
||||
// (b_i - a_i) * x <= c_i - a_i*tc - b_i*tm + b_i*S
|
||||
for (int i = 1; i <= n; ++i) {
|
||||
// 使用 ll 处理中间计算,防止溢出
|
||||
ll rhs = c[i] - a[i] * tc - b[i] * tm + b[i] * S;
|
||||
|
||||
if (a[i] < b[i]) {
|
||||
// b_i - a_i > 0, x <= floor(rhs / (b_i - a_i))
|
||||
// C++ 整数除法对于负数结果会向0取整,需要特殊处理
|
||||
ll diff = b[i] - a[i];
|
||||
ll new_upper;
|
||||
if (rhs >= 0) {
|
||||
new_upper = rhs / diff;
|
||||
} else {
|
||||
// 等价于 floor(x/y) 对于 x<0, y>0
|
||||
new_upper = (rhs - diff + 1) / diff;
|
||||
}
|
||||
upper_x = std::min(upper_x, new_upper);
|
||||
} else if (a[i] > b[i]) {
|
||||
// b_i - a_i < 0, x >= ceil(rhs / (b_i - a_i))
|
||||
// 两边同乘 -1,变为 (a_i - b_i) * x >= -rhs
|
||||
// x >= ceil(-rhs / (a_i - b_i))
|
||||
ll diff = a[i] - b[i];
|
||||
ll neg_rhs = -rhs;
|
||||
ll new_lower;
|
||||
if (neg_rhs >= 0) {
|
||||
// 等价于 ceil(x/y) 对于 x>=0, y>0
|
||||
new_lower = (neg_rhs + diff - 1) / diff;
|
||||
} else {
|
||||
new_lower = neg_rhs / diff;
|
||||
}
|
||||
lower_x = std::max(lower_x, new_lower);
|
||||
} else { // a[i] == b[i]
|
||||
// x 的系数为 0,不等式变为 0 <= rhs
|
||||
if (rhs < 0) {
|
||||
// 此不等式无解,说明该总花费 S 不可行
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果所有约束下的 x 的可行范围存在 (即下界 <= 上界),则该 S 可行
|
||||
return lower_x <= upper_x;
|
||||
}
|
||||
|
||||
|
||||
sl void solve() {
|
||||
std::cin >> n >> tc >> tm;
|
||||
for (ll i = 1; i <= n; i++) {
|
||||
std::cin >> a[i] >> b[i] >> c[i];
|
||||
}
|
||||
|
||||
// 二分答案: 最小总花费
|
||||
// 最小花费为 0, 最大花费为 tc+tm-2 (使制作时间都变为1)
|
||||
ll left = 0, right = tc + tm - 2, ans = right + 1;
|
||||
|
||||
// 注意这里二分循环条件的修改
|
||||
// [left, right] 是搜索区间
|
||||
while (left <= right) {
|
||||
ll mid = left + (right - left) / 2;
|
||||
if (checkall(mid)) {
|
||||
// 如果 mid 是一个可行的花费,我们记录它,并尝试寻找更小的花费
|
||||
ans = mid;
|
||||
right = mid - 1;
|
||||
} else {
|
||||
// 如果 mid 不可行,我们需要增加花费
|
||||
left = mid + 1;
|
||||
}
|
||||
}
|
||||
std::cout << ans << "\n";
|
||||
}
|
||||
|
||||
int main() {
|
||||
std::ios_base::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
|
||||
std::cin >> T;
|
||||
while (T--) {
|
||||
solve();
|
||||
}
|
||||
}
|
||||
50
src/10/20/P7556.cpp
Normal file
50
src/10/20/P7556.cpp
Normal file
@ -0,0 +1,50 @@
|
||||
#include <cstdint>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <istream>
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
using ll = int64_t;
|
||||
#define sl static inline
|
||||
ll T,n,arr[10],ans;
|
||||
std::set<ll >v;
|
||||
|
||||
sl void solve(){
|
||||
ans=0;
|
||||
std::cin>>n;
|
||||
v.clear();
|
||||
for(ll i=1;i<=n;i++){
|
||||
std::cin>>arr[i];
|
||||
v.emplace(arr[i]);
|
||||
}
|
||||
for(ll i=1;i<=n;i++){
|
||||
for(ll j=i+1;j<=n;j++){
|
||||
v.emplace(std::abs(arr[i]-arr[j]));
|
||||
}
|
||||
}
|
||||
for(auto a = v.begin();a!=v.end();a++){
|
||||
for(auto b=a;b!=v.end();b++){
|
||||
for(auto c=b;c!=v.end();c++){
|
||||
for(ll i=1;i<=n;i++){
|
||||
if(!(arr[i]==*a || arr[i]==*b || arr[i]==*c || arr[i]==*a+*b||arr[i]==*a+*c||arr[i]==*b+*c||arr[i]==*a+*b+*c)){
|
||||
goto nxt;
|
||||
}
|
||||
}
|
||||
ans++;
|
||||
nxt:;
|
||||
}
|
||||
}
|
||||
}
|
||||
std::cout<<ans<<"\n";
|
||||
}
|
||||
|
||||
int main(){
|
||||
std::iostream::sync_with_stdio(false);
|
||||
std::cin.tie(nullptr);
|
||||
|
||||
std::cin>>T;
|
||||
while(T--){
|
||||
solve();
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user