2024-2025 ICPC, NERC, Southern and Volga Russian Regional Contest 個人題解(A,B,C,G,J,K,L,N)
Dashboard - 2024-2025 ICPC, NERC, Southern and Volga Russian Regional Contest (Unrated, Online Mirror, ICPC Rules, Preferably Teams) - Codeforces
難度排序
由低到高
N、J、L、C、A、G、K、B。
火車頭
#include <bits/stdc++.h>
using namespace std;
#define ft first
#define sd second
#define yes cout << "yes\n"
#define no cout << "no\n"
#define Yes cout << "Yes\n"
#define No cout << "No\n"
#define YES cout << "YES\n"
#define NO cout << "NO\n"
#define pb push_back
#define eb emplace_back
#define all(x) x.begin(), x.end()
#define all1(x) x.begin() + 1, x.end()
#define unq_all(x) x.erase(unique(all(x)), x.end())
#define unq_all1(x) x.erase(unique(all1(x)), x.end())
#define inf 0x3f3f3f3f
#define infll 0x3f3f3f3f3f3f3f3fLL
#define RED cout << "\033[91m" // 紅色
#define GREEN cout << "\033[92m" // 綠色
#define YELLOW cout << "\033[93m" // 藍色
#define BLUE cout << "\033[94m" // 品紅
#define MAGENTA cout << "\033[95m" // 青色
#define CYAN cout << "\033[96m" // 青色
#define RESET cout << "\033[0m" // 重置
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
// typedef __int128_t i128;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ll, int> pli;
typedef pair<string, ll> psl;
typedef tuple<int, int, int> ti3;
typedef tuple<ll, ll, ll> tl3;
typedef tuple<ld, ld, ld> tld3;
typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<string> vs;
typedef vector<vi> vvi;
typedef vector<vl> vvl;
// std::mt19937_64 rng(std::chrono::steady_clock::now().time_since_epoch().count());
template <typename T>
inline T read()
{
T x = 0;
int y = 1;
char ch = getchar();
while (ch > '9' || ch < '0')
{
if (ch == '-')
y = -1;
ch = getchar();
}
while (ch >= '0' && ch <= '9')
{
x = (x << 3) + (x << 1) + (ch ^ 48);
ch = getchar();
}
return x * y;
}
template <typename T>
inline void write(T x)
{
if (x < 0)
{
putchar('-');
x = -x;
}
if (x >= 10)
{
write(x / 10);
}
putchar(x % 10 + '0');
}
/*#####################################BEGIN#####################################*/
void solve()
{
}
int main()
{
ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
// freopen("test.in", "r", stdin);
// freopen("test.out", "w", stdout);
int _ = 1;
std::cin >> _;
while (_--)
{
solve();
}
return 0;
}
/*######################################END######################################*/
// 連結:
A. Bonus Project
有一個由 \(n\) 名軟體工程師組成的團隊,編號從 1 到 \(n\)。他們的老闆承諾,如果他們完成一個額外的專案,就會給他們發獎金。該專案總共需要 \(k\) 個工作單位。答應給第 \(i\) 位工程師的獎金是 \(a_i\) 布勒斯。老闆沒有給工程師分配具體任務,而是希望每個工程師都能自願完成某個整數的工作單位。只有當專案完成時,整個團隊才會獲得獎金;換句話說,如果專案中自願完成的工作單位總數大於或等於 \(k\),整個團隊才會獲得獎金。
每位工程師可完成的工作量不受限制。不過,所有工程師都會珍惜自己的勞動成果。第 \(i\) 位工程師估計他們的一個工作單位為 \(b_i\) 布林。如果支付了獎金,那麼第 \(i\) 位工程師完成 \(c\) 個單位的工作所獲得的收益 \(s_i\) 定義為 \(s_i = a_i - c \cdot b_i\)。如果不支付獎金,工程師將不會自願完成任何工作。
工程師們在一起工作多年,因此他們知道獎金將如何分配以及同事們對勞動的重視程度。也就是說,團隊中的每個工程師都知道所有的 \(a_i\) 和所有的 \(b_i\)。
工程師們都渴望獲得獎金,因此他們之間商定了以下工作分配流程:
第一位工程師說:"我將完成 \(c_1\) 個工作單位",其中 \(c_1\) 是一個非負整數;
然後,第二個工程師說:"我將完成 \(c_2\) 個工作單位",其中 \(c_2\) 是一個非負整數;
......依此類推;
最後,第 \(n\) 位工程師說:"我將完成 \(c_n\) 個工作單位",其中 \(c_n\) 是一個非負整數。
每個工程師都會發出 \(c_i\) 的聲音,使自己的利益 \(s_i\) 最大化。如果預期收益為零,工程師仍會同意工作以獲得經驗,並幫助同事獲得獎金。但是,如果由於某種原因預期收益為負(工程師需要完成過多的工作或專案無法完成),該工程師將根本不工作(完成零工作量)。
鑑於每個工程師的行為都是完美的,你的任務是找出每個工程師所表達的數字 \(c_i\)。
輸入
第一行包含兩個整數 \(n\) 和 \(k\) ( \(1 \leq n \leq 1000\) ; \(1 \leq k \leq 10^6\) )——分別是公司的工程師人數和專案所需的工作單位數量。
第二行包含 \(n\) 個整數 \(a_1, a_2, \ldots, a_n\) ( \(1 \leq a_i \leq 10^9\) ),其中 \(a_i\) 是專案完成後將支付給第 \(i\) 個工程師的獎金。
第三行包含 \(n\) 個整數 \(b_1, b_2, \ldots, b_n\) ( \(1 \leq b_i \leq 1000\) ),其中 \(b_i\) 是第 \(i\) 位工程師的工作單位成本。
輸出
列印 \(n\) 個整數 \(c_1, c_2, \ldots, c_n\) ( \(0 \leq c_i \leq k\) )——在每個工程師都表現最優的情況下,每個工程師完成的工作量。請注意,答案是唯一的。
示例
輸入
3 6
4 7 6
1 2 3
輸出
1 3 2
輸入
3 12
4 7 6
1 2 3
輸出
0 0 0
輸入
3 11
6 7 8
1 2 3
輸出
6 3 2
提示
在第一個示例中,工程師們在他們之間分配了工作並獲得了獎金,儘管第三位工程師的收益為零。
在第二個示例中,獎金專案需要的工作單位太多,因此工程師們不工作更有利。
解題思路
由於工作分配流程是從前往後的,因此越後面的人,選擇權越小。
倒著列舉,將工作儘可能分配給後面的人即可。
搞不定資料範圍設定成1000幹啥,嚇人嗎
實現程式碼
void solve()
{
int n, k;
cin >> n >> k;
vi a(n), b(n);
for (int i = 0; i < n; i++)
{
cin >> a[i];
}
for (int i = 0; i < n; i++)
{
cin >> b[i];
}
vi ans(n);
int now = 0;
for (int i = n - 1; i >= 0; i--)
{
int num = a[i] / b[i];
num = min(num, k - now);
ans[i] = num;
now += num;
if (now == k)
break;
}
if (now < k)
{
for (int i = 0; i < n; i++)
{
cout << "0 ";
}
cout << "\n";
}
else
{
for (int i = 0; i < n; i++)
{
cout << ans[i] << " \n"[i == n - 1];
}
}
}
B. Make It Equal
給你一個大小為 \(n\) 的整數陣列 \(a\)。陣列元素的編號從 1 到 \(n\)。
您可以執行以下任意次數的操作(可能為 0 次):從 1 到 \(n\) 之間選擇一個索引 \(i\);將 \(a_i\) 減少 2,並將 \(a_{(i \mod n) + 1}\) 增加 1。
執行這些操作後,陣列中的所有元素都應是非負等整數。
你的任務是計算最少需要執行的運算次數。
輸入
第一行包含一個整數 \(t\) ( \(1 \leq t \leq 10^4\) )——測試用例數。
每個測試用例的第一行包含一個整數 \(n\) ( \(2 \leq n \leq 2 \cdot 10^5\) )。
每個測試用例的第二行包含 \(n\) 個整數 \(a_1, a_2, \ldots, a_n\) ( \(1 \leq a_i \leq 10^9\) )。
輸入的附加限制:所有測試用例中 \(n\) 的總和不超過 \(2 \cdot 10^5\)。
輸出
對於每個測試用例,列印一個整數——你必須執行的最小運算元。如果不可能使陣列中的所有元素都相等,則列印 -1。
示例
輸入
3
2
1 1
3
1 3 2
4
2 1 2 6
輸出
0
-1
3
解題思路
觀察發現,如果一個陣列全部元素相等,那麼我們可以對所有元素進行一次操作,從而讓所有元素都減 \(1\) 。
因此,如果一個陣列能夠透過操作使得陣列元素全部相等,且使得相等的最大元素為 \(x\) 那麼,我們一定也可以構造出 \([1,x-1]\) 相等的陣列。
因此,最後的相等元素 \(x\) 具有二段性,所以我們可以二分 \(x\) 是否為最大的最終相等元素。
考慮設計檢查函式。
我們可以對所有數進行操作,使得 $\forall a_i \le x $,然後檢查是否 $\forall a_i = a_{i+1} $。
對於一個數 \(a_i\) 要把它變為 \(x\) ,當 \(a_i \le x\) 肯定是不操作;當 \(a_i>x\) 時,如果 \(a_i-x\) 為奇數,就先對 \(a_{i-1}\) 操作一次,讓其變成偶數,然後對其操作 \(\frac{a_{i}-x}{2}\) 次。
如果只操作一遍,也許任然存在 \(a_i\gt x\) ,因此我們需要迴圈操作 直到$\forall a_i \le x $。
看上去可能超時,考慮極限情況 \(x=0,\forall a_i=10^9\)。
由於我們設計的操作函式每次會將 \(a_i\) 的值減半加到 \(a_{i+1}\) ,因此對於整體而言,我們每次都減去了 \(\frac{a_i}{2}\) ,極限情況下陣列和為 \(n\times a_i\) ,因此我們總共會操作 \(log_2{a_i}\times n\) 。因此,我們檢查函式的時間複雜度為 \(O(nlogV)\) 。
實現程式碼
void solve()
{
int n;
cin >> n;
vi a(n);
ll sum = 0;
for (int i = 0; i < n; i++)
{
cin >> a[i];
sum += a[i];
}
auto check = [&](int x) -> bool
{
vi temp = a;
while (1)
{
bool flag = true;
for (int i = 0; i < n; i++)
{
if (temp[i] <= x)
continue;
flag = false;
if ((temp[i] - x) & 1)
{
temp[(i - 1 + n) % n] -= 2;
temp[i]++;
}
temp[(i + 1) % n] += (temp[i] - x) / 2;
temp[i] = x;
}
if (flag)
break;
}
for (int i = 0; i < n; i++)
{
if (temp[i] != x)
return false;
}
return true;
};
int l = 0, r = (sum + n - 1) / n;
while (l < r)
{
int mid = (l + r + 1) >> 1;
if (check(mid))
l = mid;
else
r = mid - 1;
}
if (check(r))
cout << sum - 1ll * r * n << "\n";
else
cout << "-1\n";
}
C. DIY
給你一個由 \(n\) 個整數 \(a_1, a_2, \ldots, a_n\) 組成的列表。你需要從列表中選取 8 個元素作為四個點的座標。這四個點應該是邊平行於座標軸的矩形的角。您的任務是選取座標,使得到的矩形具有儘可能大的面積。矩形可以是退化矩形,即其面積可以是 0。每個整數在列表中出現的次數不限(或更少)。
輸入
第一行包含一個整數 \(t\) ( \(1 \leq t \leq 25000\) )——測試用例數。
每個測試用例的第一行包含一個整數 \(n\) ( \(8 \leq n \leq 2 \cdot 10^5\) )。
每個測試用例的第二行包含 \(n\) 個整數 \(a_1, a_2, \ldots, a_n\) ( \(-10^9 \leq a_i \leq 10^9\) )。
輸入的附加限制:所有測試用例中 \(n\) 的總和不超過 \(2 \cdot 10^5\)。
輸出
對於每個測試用例,列印答案如下:
如果不可能構造出符合語句限制條件的矩形,則列印包含 NO(不區分大小寫)字樣的一行;
否則,在第一行列印 YES(不區分大小寫)。在第二行中,列印 8 個整數 \(x_1, y_1, x_2, y_2, x_3, y_3, x_4, y_4\)——矩形各角的座標。您可以按照任意順序列印角的座標。
示例
輸入
3
16
-5 1 1 2 2 3 3 4 4 5 5 6 6 7 7 10
8
0 0 -1 2 2 1 1 3
8
0 0 0 0 0 5 0 5
輸出
YES
1 2 1 7 6 2 6 7
NO
YES
0 0 0 5 0 0 0 5
解題思路
對於是否可以構建出矩陣,我們只需要檢查是否存在 \(4\) 對以上相同的數即可。
對於如何找尋最大矩形,如果所以數的數量都大於 \(4\) ,那麼我們一定是貪心的選擇最大和最小的數作為矩形的邊角,由此推得,我們一定是選擇最大和次大,最小和次小的數對來構造矩形。
實現程式碼
void solve()
{
int n;
cin >> n;
map<int, int> mp;
for (int i = 0; i < n; i++)
{
int x;
cin >> x;
mp[x]++;
}
int cnt = 0;
for (auto x : mp)
{
cnt += x.sd / 2;
}
if (cnt < 4)
{
NO;
return;
}
int mx1 = -inf;
int mx2 = -inf;
int mn1 = inf;
int mn2 = inf;
for (auto x : mp)
{
if (x.sd >= 4)
{
mx1 = max(mx1, x.ft);
mx2 = max(mx2, x.ft);
mn1 = min(mn1, x.ft);
mn2 = min(mn2, x.ft);
}
else if (x.sd >= 2)
{
if (x.ft > mx1)
{
mx2 = mx1;
mx1 = x.ft;
}
else if (x.ft > mx2)
{
mx2 = x.ft;
}
if (x.ft < mn1)
{
mn2 = mn1;
mn1 = x.ft;
}
else if (x.ft < mn2)
{
mn2 = x.ft;
}
}
}
YES;
cout << mn1 << " " << mn2 << " " << mn1 << " " << mx1 << " " << mx2 << " " << mn2 << " " << mx2 << " " << mx1 << "\n";
}
G. Guess One Character
這是一個互動式問題。您必須在列印完每一行後立即使用 flush 操作。例如,在 C++ 中應使用函式 fflush(stdout) 或 cout.flush(),在 Java 或 Kotlin 中應使用 System.out.flush(),在 Python 中應使用 sys.stdout.flush()。
陪審團有一個由字元 0 和/或 1 組成的字串 \(s\)。該字串的長度為 \(n\)。
您可以進行以下查詢:
- \(t\) — " \(t\) 作為連續子串在 \(s\) 中出現了多少次?" 在這裡, \(t\) 應該是一個由字元 0 和/或 1 組成的字串;其長度至少為 1 ,最多為 \(n\)。例如,如果字串 \(s\) 是 111011,而字串 \(t\) 是 11,那麼查詢的回覆就是 3。
您必須透過不超過 3 的查詢猜出字串 \(s\) 中的至少一個字元。需要注意的是,給出答案並不算一次詢問。
在每個測試和每個測試用例中,字串 \(s\) 都是事先固定的。
互動
最初,陪審團程式傳送一個整數 \(t\) ( \(1 \leq t \leq 1000\) )——測試用例數。
在每個測試用例開始時,陪審團程式傳送一個整數 \(n\) ( \(2 \leq n \leq 50\) )——字串的長度。
之後,您的程式可以透過列印以下一行向陪審團程式提交查詢(列印完一行後不要忘記重新整理輸出!):
1 \(t\) 表示詢問 " \(s\) 中的連續子串 \(t\) 出現了多少次?"
對於每個查詢,陪審團都會在單獨一行中列印一個整數。它要麼是查詢的答案,如果查詢是正確的,並且沒有超出查詢限制;或者是整數 −1 ,如果您的查詢不正確(例如,未滿足約束 \(1 \leq |t| \leq n\) 或字串 \(t\) 包含 0 和 1 以外的字元),或者您在處理當前測試用例時提出了太多查詢。
要提交答案,您的程式應按以下格式傳送一行(列印完一行後不要忘記重新整理輸出!):
0 \(i\) \(c\),其中 \(1 \leq i \leq n\) 和 \(c\) 要麼為 0 要麼為 1,即 \(s_i = c\)。
如果您的猜測正確,陪審團程式將在單獨一行中列印一個整數 1 ,表示您可以進入下一個測試用例(如果是最後一個測試用例,則終止程式),並且您提出的詢問次數將被重置。如果不正確,陪審團程式將在另一行列印一個整數 −1 。
程式收到 −1 作為響應後,應立即終止。這將導致您的提交收到 "錯誤答案" 的裁決。如果您的程式沒有終止,則您的提交結果為 "未定義"。
示例
輸入
3 // 3 測試用例
3 // 字串長度為 3
1 // 101 出現一次
1 // 猜測正確
2 // 字串長度為 2
0 // 00 出現零次
0 // 0 出現零次
1 // 猜測正確
2 // 字串長度為 2
1 // 1 出現一次
0 // 01 出現零次
1 // 猜測正確
輸出
1 101 // 查詢 101 出現多少次
0 2 0 // 猜測:s[2] 是 0
1 00 // 查詢 00 出現多少次
1 0 // 查詢 0 出現多少次
0 1 1 // 猜測:s[1] 是 1
1 1 // 查詢 1 出現多少次
1 01 // 查詢 01 出現多少次
0 2 0 // 猜測:s[2] 是 0
注意
在示例中,有 3 個測試用例:101、11 和 10。請注意,所有註釋內容(// 後的內容)不會在實際問題中列印,您也不應列印這些內容。空行也是為了方便您而新增的,陪審團程式不會列印它們,您的解決方案也不應列印任何空行。
解題思路
將字元除串按長度為 \(1\) 進行劃分,我們可以得到 \(0\) 和 \(1\) 兩種子字串,按長度為 \(2\) 進行劃分,我們可以得到 \(00\) , \(01\) , \(11\) 和 \(10\) 四種子字串。
觀察發現,如果只存在 \(00\) 和 \(01\) 字串,那麼 \(0\) 子字串的數量將等於這兩種字串數量相加,那麼最後一為一定是 \(1\) 。
實現程式碼
int query(string s)
{
printf("1 %s\n", s.c_str());
fflush(stdout);
return read<int>();
}
void answer(int pos, char c)
{
printf("0 %d %c\n", pos, c);
fflush(stdout);
}
void solve()
{
int n = read<int>();
int n0 = query("0");
int n00 = query("00");
int n01 = query("01");
if (n00 + n01 == n0)
answer(n, '1');
else
answer(n, '0');
int res = read<int>();
assert(res == 1);
}
J. Waiting for...
Monocarp 正在公交車站等車。不幸的是,有很多人也想乘坐公共汽車。
您會得到一份兩類事件的清單:
- \(B \, b_i\) - 一輛有 \(b_i\) 個空座位的公交車到站;
- \(P \, p_i\) - \(p_i\) 人到達車站。
這些事件按時間順序排列。
當一輛公共汽車到達時,會發生以下情況。公交車站的所有人(除了 Monocarp)都試圖進入公交車。如果有足夠的空位,他們就都上車。否則,會有一些人留在公交車站(進入公交車的人數等於空餘座位數)。
如果所有的人(除了 Monocarp)都進入公交車後還有至少一個空座位,那麼 Monocarp 也可以決定進入這輛公交車(但他可能會選擇等另一輛公交車)。對於每輛公交車,您都必須確定 Monocarp 是否有可能乘坐該公交車。
輸入
第一行包含一個整數 \(n\) - 事件數量。 \((1 \leq n \leq 10^3)\)
然後是 \(n\) 行。其中第 \(i\) 行包含第 \(i\) 個事件的描述,格式如下:
- \(B \, b_i\) \((1 \leq b_i \leq 10^6)\) - 一輛有 \(b_i\) 個空座位的公交車到站;
- \(P \, p_i\) \((1 \leq p_i \leq 10^6)\) - \(p_i\) 人到達車站。
輸入的其他限制條件:至少有一個 \(B\) 型別的事件。
輸出
對於 \(B\) 型別的每個事件,如果 Monocarp 有可能佔用相應的公交車,則列印 "YES",否則列印 "NO"(不區分大小寫)。
示例
輸入
10
P 2
P 5
B 8
P 14
B 5
B 9
B 3
P 2
B 1
B 2
輸出
YES
NO
NO
YES
NO
YES
解題思路
簽到題,按題意進行模擬即可。
實現程式碼
void solve()
{
int n;
cin >> n;
ll sum = 0;
while (n--)
{
char c;
int x;
cin >> c >> x;
if (c == 'P')
sum += x;
else
{
sum -= x;
if (sum < 0)
{
YES;
sum = 0;
}
else
{
NO;
}
}
}
}
K. Grid Walk
您有一個 \(n \times n\) 網格和兩個整數 \(a\) 和 \(b\)。行和列的編號都是從 1 到 \(n\)。我們把第 \(i\) 行和第 \(j\) 列的交點處的單元格記為 \((i,j)\)。
您現在站在 \((1,1)\) 單元格,想要移動到 \((n,n)\) 單元格。
假設您現在位於 \((i,j)\) 單元格;如果存在相應的單元格,您可以一步移動到 \((i,j+1)\) 單元格或 \((i+1,j)\) 單元格。
我們將 \((i,j)\) 單元格的成本定義為
(此處,\(\text{gcd}(x,y)\) 表示 \(x\) 和 \(y\) 的最大公約數)。從 \((1,1)\) 到 \((n,n)\) 的路徑成本是所訪問單元格(包括起始單元格和終點單元格)的成本之和。
找出成本最小的路線並列印其成本。
輸入
唯一一行包含三個整數 \(n\)、\(a\) 和 \(b\) \((2 \leq n \leq 10^6; 1 \leq a,b \leq 10^6)\)。
輸出
列印一個整數——從 \((1,1)\) 到 \((n,n)\) 的最便宜路線的成本。
示例
輸入
4 2 4
輸出
21
輸入
10 210 420
輸出
125
注意
第一個示例在上面的圖片中描述。
解題思路
觀察發現,無論我們如何操作,我們一定至少會加一遍所有的 \(\text{gcd}(i,a)\) 和 \(\text{gcd}(j,b)\) ,我們可操作的為剩下需要加上的值 \(v\)。
考慮極限情況: \(gcd(n,a)=1\) 且 \(gcd(n,b)=1\) ,則我們一定是走邊角最優,除了必加值外,我們剩下加上的值都是 \(1\) 。
因此,對於任意 \(a,b,n\) 來說,我們一定是走到從第一行一直向右走,走到最遠的 \(\text{maxi}=i\) 使得 \(gcd(a,i)=1\) ,然後再一直向下走,走到最遠的 \(\text{maxj}=j\) 使得 \(gcd(b,j)=1\) 。然後再考慮剩下的位置這麼走。
我們設 \(rn=n-\text{maxi}\) , \(rm=n-\text{maxj}\) ,可以發現 \(rn\) 和 \(rm\) 都比較小。
因為質數和任何數都互質,且質數在 \(10^6\) 內分佈較為稠密,質數之間的最大間隔不會超過 \(200\),因此 \(rn \lt 200,rm \lt 200\)。可以直接進行 \(n^2\) 的 dp 。
狀態轉移方程:\(dp[i][j]=\min(dp[i-1][j],dp[i][j-1])+\gcd(i,a)+\gcd(j,b)\)
實現程式碼
void solve()
{
int n, a, b;
cin >> n >> a >> b;
int maxi = 1;
vi ga(n + 1);
for (int i = 1; i <= n; i++)
{
ga[i] = __gcd(i, a);
if (ga[i] == 1)
maxi = i;
}
int maxj = 1;
vi gb(n + 1);
for (int i = 1; i <= n; i++)
{
gb[i] = __gcd(i, b);
if (gb[i] == 1)
maxj = i;
}
int ans = maxi + maxj - 2;
for (int i = 1; i <= maxi; i++)
{
ans += ga[i];
}
for (int i = 1; i <= maxj; i++)
{
ans += gb[i];
}
int rn = n - maxi;
int rm = n - maxj;
vvi dp(rn + 1, vi(rm + 1, inf));
dp[0][0] = 0;
for (int i = 0; i <= rn; i++)
{
for (int j = 0; j <= rm; j++)
{
if (i > 0)
dp[i][j] = min(dp[i][j], dp[i - 1][j] + ga[maxi + i] + gb[maxj + j]);
if (j > 0)
dp[i][j] = min(dp[i][j], dp[i][j - 1] + ga[maxi + i] + gb[maxj + j]);
}
}
ans += dp[rn][rm];
cout << ans << "\n";
}
L. Bridge Renovation
最近,Monocarp 開始擔任他家附近一個公園的園長。公園很大,甚至有一條小河把它分成幾個區域。河上建有幾座橋。其中有三座橋特別老舊,需要修理。
三座橋的長度相同,但寬度不同。它們的寬度分別為 18、21 和 25 個單位。
在公園翻新過程中,Monocarp 必須用新木板替換作為橋面的舊木板。
木板的標準長度為 60 個單位。Monocarp 已經知道每座橋需要 \(n\) 塊木板。但由於橋的寬度不同,第一座橋需要長度為 18 的 \(n\) 塊木板,第二座橋需要長度為 21 的 \(n\) 塊木板,最後一座橋需要長度為 25 的 \(n\) 塊木板。
負責翻修的工人可以將木板切割成若干部分,但拒絕將木板連線起來,因為這樣會產生薄弱點,而且看起來很難看。
Monocarp 想買儘可能少的木板,但卻苦於計算不出所需木板的數量。您能幫助他嗎?
輸入
第一行也是唯一一行包含一個整數 \(n\) \((1 \leq n \leq 1000)\)——三座橋所需的木板數量。
輸出
列印一個整數——如果木板可以切割成若干部分,則 Monocarp 覆蓋所有三座橋所需的最小標準長度木板數量(60 單位)。
示例
輸入
1
輸出
2
輸入
3
輸出
4
輸入
1000
輸出
1167
注意
在第一個示例中,可以將一塊長度為 60 的木板切割成三塊長度為 25、18 和 17 的木板,再將另一塊長度為 60 的木板切割成兩塊長度為 39 和 21 的木板。這樣,Monocarp 將會得到所有所需的木板。
解題思路
觀察發現第一種和第二種的木板可以任意三三組合,剩下的和第三種只能任意兩兩組合,因此答案為 \(\lfloor \frac{2n}{3} \rfloor +\lceil \frac{2n\%3+n}{2} \rceil\)
實現程式碼
void solve()
{
int n;
cin >> n;
cout << (2 * n) / 3 + (2 * n % 3 + n + 1) / 2 << "\n";
}
N. Fixing the Expression
表示式是由三個字元組成的字串,其中第一個和最後一個字元是數字(從 0 到 9),中間的字元是比較符號(<, = 或 >)。
如果比較符號與數字匹配,則表示式為真(例如,如果第一位數字嚴格小於最後一位數字,則比較符號應為 <)。
例如,表示式 1<3、4>2、0=0 為真,而 5>5、7<3 不是真。
給你一個字串 \(s\),這是一個表示式。請儘可能少地更改字元,使 \(s\) 成為一個真表示式。請注意,如果 \(s\) 已經為真,則應保持原樣。
輸入
第一行包含一個整數 \(t\) \((1 \leq t \leq 300)\) - 測試用例數。
每個測試用例包含一行字串 \(s\) \((|s| = 3\),\(s\) 的第一個和最後一個字元為數字,第二個字元為比較符號)。
輸出
對於每個測試用例,列印一個由 3 個字元組成的字串,即透過更改 \(s\) 中儘可能少的字元而得到的真表示式。如果有多個答案,則列印其中任何一個。
示例
輸入
5
3<7
3>7
8=9
0=0
5<3
輸出
3<7
8>7
8<9
0=0
0<3
解題思路
簽到題,根據兩邊值的關係去修改符號即可。
實現程式碼
void solve()
{
string s;
cin >> s;
int a = s[0];
int b = s[2];
if (a < b)
s[1] = '<';
else if (a == b)
s[1] = '=';
else
s[1] = '>';
cout << s << "\n";
}
封面畫師id:清風殘影Sid