Educational Codeforces Round 80 A - D題題解(又是卡很久的一場比賽)
第八場
CodeForces - 1288A. Deadline
Example
input
3
1 1
4 5
5 11
output
YES
YES
NO
Note
In the first test case, Adilbek decides not to optimize the program at all, since \(d≤n\).
In the second test case, Adilbek can spend \(1\) day optimizing the program and it will run \(⌈\frac52⌉=3\) days. In total, he will spend \(4\)
In the third test case, it's impossible to fit in the limit. For example, if Adilbek will optimize the program \(2\) days, it'll still work \(⌈\frac{11}{2+1}⌉=4\) days.
題意:
\(Adilbek\) 有一個程式設計任務,總工期為 \(n\) 天,直接暴力完成需要 \(d\) 天。但他可以選擇花 \(x\) 天進行優化,然後再花 \(⌈\frac{d}{x + 1}⌉\)
思路:
如果暴力完成天數小於工期則不需要去特地優化,不然的話需要進行優化但優化天數是不能超過 工期數(即 \(x < n\))。
詳解看程式碼更好理解。
#include<bits/stdc++.h> #define ms(a,b) memset(a,b,sizeof a) using namespace std; typedef long long ll; const int N = 1e5 + 100; ll _, n, d, a[N], i, j; void solve() { cin >> n >> d; if (d <= n) { cout << "YES" << endl; return; } for (int x = 1; x < d && x <= n; ++x) { if ((x + ceil((float)d / (x + 1))) <= n) {//必須要先提高精度(float化)不然在除的時候會導致錯誤,如4/3 = 1.333 = 1發生錯誤 cout << "YES" << endl; return; } } cout << "NO" << endl; } int main() { //freopen("in.txt", "r", stdin); ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0); cin >> _; while (_--) solve(); }
CodeForces - 1288B. Yet Another Meme Problem
input
3
1 11
4 2
191 31415926
output
1
0
1337
Note
There is only one suitable pair in the first test case: \(a=1, b=9 (1+9+1⋅9=19)\).
題目內部圖片:
題意:
給定\(A,B\) 求$ 1≤a≤A, 1≤b≤B1$ 有多少對(a,b)使\(a⋅b+a+b=conc(a,b)\) 成立。
思路:
仔細分解一下所給的公式:
\[a * b + a + b = conc(a,b)\\ a * b + a + b = a * 10^{|num|} + b \\ | num | 是b的十進位制表示長度。\\ a * b + a = a * 10^{|num|}\\ b + 1 = 10^{|num|}\\ 因此,b總是看起來像99…99。 因此,答案是a *(| num + 1 | -1)。 \]
#include<bits/stdc++.h>
#define ms(a,b) memset(a,b,sizeof a)
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 1e5 + 100;
ll _, n, m, a[N], i, j;
void solve() {
ll A, B; cin >> A >> B;
ll weinum = 0, i = B;
bool flag = true;
while (i) {
weinum++;
i /= 10;
}
i = B;
while (i) {
if (i % 10 != 9) {
flag = false;
break;
}
i /= 10;
}
if (flag)cout << A * weinum << endl;
else cout << A * (weinum - 1) << endl;
}
int main() {
//freopen("in.txt", "r", stdin);
ios_base::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> _; while (_--) solve();
}
#python
for t in range(int(input())):
a, b = map(int, input().split())
print(a * (len(str(b + 1)) - 1))
1288C - Two Arrays
組合數學問題。
讓我們考慮以下順序:
\[a_1,a_2,…,a_m,b_m,b_{m-1},…,b_1。 \]
它的長度為$ 2m \(的序列以降序排列,其中每個序列的每個元素都是\) 1 \(和\) n $之間的整數。
我們可以通過簡單的組合來找到此類序列的數量-它是與重複結合在一起的。 所以答案是
\[\begin{pmatrix}n+2m−1\\\\2m\end{pmatrix} = (n+2m−1)!(2m)!/(n−1)! \]
#python
from math import factorial as fact
mod = 10**9 + 7
def C(n, k):
return fact(n) // (fact(k) * fact(n - k))
n, m = map(int, input().split())
print(C(n + 2*m - 1, 2*m) % mod)
1288D - Minimax Problem
思路:來自CF官網
我們將使用二進位制搜尋來解決該問題。 假設我們想知道答案是否不少於x。
每個陣列都可以由一個m位掩碼錶示,其中如果陣列的第i個元素不少於x,則第i個位為1;如果第i個元素小於x,則第i個位為0。 如果要驗證答案不小於x,則必須選擇兩個陣列,使它們的掩碼的按位或為\(2^m-1\)。
檢查所有成對的陣列太慢。 取而代之的是,我們可以將相同掩碼錶示的陣列視為相等-這樣,我們將不會有超過\(2^m\)個不同的陣列,並且可以迭代\(4^m\)對。 總體而言,該解決方案在\(O(logA(4^m + nm))\)下工作。
C++程式碼實現:
#include<bits/stdc++.h>
using namespace std;
int n, m;
vector<vector<int> > a;
int a1, a2;
bool can(int mid)
{
vector<int> msk(1 << m, -1);
for(int i = 0; i < n; i++)
{
int cur = 0;
for(int j = 0; j < m; j++)
if(a[i][j] >= mid)
cur ^= (1 << j);
msk[cur] = i;
}
if(msk[(1 << m) - 1] != -1)
{
a1 = a2 = msk[(1 << m) - 1];
return true;
}
for(int i = 0; i < (1 << m); i++)
for(int j = 0; j < (1 << m); j++)
if(msk[i] != -1 && msk[j] != -1 && (i | j) == (1 << m) - 1)
{
a1 = msk[i];
a2 = msk[j];
return true;
}
return false;
}
int main()
{
scanf("%d %d", &n, &m);
a.resize(n, vector<int>(m));
for(int i = 0; i < n; i++)
for(int j = 0; j < m; j++)
scanf("%d", &a[i][j]);
int lf = 0;
int rg = int(1e9) + 43;
while(rg - lf > 1)
{
int m = (lf + rg) / 2;
if(can(m))
lf = m;
else
rg = m;
}
assert(can(lf));
printf("%d %d\n", a1 + 1, a2 + 1);
}