1. 程式人生 > 實用技巧 >Educational Codeforces Round 80 A - D題題解(又是卡很久的一場比賽)

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\)

days and will fit in the limit.

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}⌉\)

天執行。如果可以在工期內完成則輸出 \(YES\) 不然輸出 \(NO\)

思路:

如果暴力完成天數小於工期則不需要去特地優化,不然的話需要進行優化但優化天數是不能超過 工期數(即 \(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);
}