Educational Codeforces Round 135 (Rated for Div. 2) - E. Red-Black Pepper
exgcd
题意
给 个菜,每个菜可以加红辣椒或黑辣椒,分别可以获得 分;
有 个商店,第 i 个商店包含 , 表示只打包卖红辣椒 个,黑辣椒 个,即必须有 , 且
求若分别去这 个商店买辣椒,分别最多能获得多少分
思路
- 假设全部加黑辣椒,求出当前的答案 (不用管是否满足有解)
- 令 , 从大到小排序,求出前缀和 ,若能加 k 个红辣椒,则就取前 k 个
- 用 exgcd 解出一组解 , 且 为最小非负整数解,此时若 则返回 -1
- 令 , 通解为 , 并找出满足 的最大的
- 由于 是单峰的,三分即可
- 也可以找到峰,求峰两侧的 x 对应的最大值即可(详细见代码)
代码
#include <bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
typedef pair<int, int> PII;
const int N = 3e5 + 10;
int n;
ll c[N], s[N];
ll ans;
int idx;
ll exgcd(ll a, ll b, ll &x, ll &y)
{
if (b == 0)
{
x = 1;
y = 0;
return a;
}
ll xx, yy;
ll d = exgcd(b, a % b, xx, yy);
x = yy, y = xx - a / b * yy;
return d;
}
ll solve(ll a, ll b)
{
ll x, y;
ll d = exgcd(a, b, x, y);
if (n % d)
return -1;
x *= n / d, y *= n / d;
ll bb = b / d;
x %= bb;
if (x < 0)
x += bb;
y = (n - x * a) / b;
if (y < 0)
return -1;
int l = x, r = (n - l * a) / (bb * a) * bb + l;
if (l * a >= idx)
return s[l*a] + ans;
if (r * a <= idx)
return s[r*a] + ans;
int lim = (idx - l * a) / (bb * a) * bb + l;
return max(s[lim * a], s[(lim + bb) * a]) + ans;
}
int main()
{
ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
cin >> n;
for (int i = 1; i <= n; i++)
{
int x, y;
cin >> x >> y;
c[i] = x - y;
ans += y;
}
sort(c + 1, c + n + 1, greater<ll>());
for (int i = 1; i <= n; i++)
{
s[i] = s[i-1] + c[i];
if (c[i] >= 0)
idx = i;
}
int q;
cin >> q;
while(q--)
{
int a, b;
cin >> a >> b;
cout << solve(a, b) << endl;
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
· 零经验选手,Compose 一天开发一款小游戏!