2023 年上海市大学生程序设计竞赛 - 五月赛A,B,C

发布时间 2023-06-26 21:06:15作者: Ke_scholar

A. 选择

多造几组数据可以发现

\(dp[n] = dp[n / 2] + 1\).

假如一个序列为\(\{1,2,\cdots,n\}\),那我们从\(n/2\)后都减去\(n/2\),序列就变为了\(\{1,2,\cdots,n/2,1,2,\cdots,n/2\}\),那么我们只需要\(n/2\)时次数最少得方案即可.

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <cmath>
#include <stack>
#include <numeric>
#define inf 0x3f3f3f3f
#define yes cout << "YES" << endl
#define no cout << "NO" << endl
#define endl '\n'
#define int long long

using namespace std;

const int N = 1e6 + 10, mod = 1e9 + 7;
typedef unsigned long long ll;
typedef pair<int,int> PII;

void solve(){
    cin >> n;
    vector<int> dp(n + 1);
    dp[1] = 1;
    for(int i = 1;i <= n;i ++)
        dp[i] = dp[i / 2] + 1;
    cout << dp[n] << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    int Ke_scholar  = 1;
//    cin >> Ke_scholar;
    while(Ke_scholar--)
        solve();
    return 0;
}

/*
*/

B. 锐评

假设答案至少为 \(r\),且 \(a,b\) 已经完成操作,那么我们可以有这样的不等式:

\(\frac {a} {a + b} \geq r \Rightarrow (1 - r) a - rb \geq 0.\)

因此,给 \(a\) 加 1,\(b\) 减 1 的收益是线性的,因此一定在 \(a\) 最大和 \(b\) 最小时取到极值,对两者取 \(max\) 即可。

\(b\)取最小时,记得把多出来的钱刷好评(另外如果你一直过不了第一个点的话,可以试试把\(scanf\)换成\(cin\),很奇怪\(\cdots\))

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define endl '\n'
#define int long long
using namespace std;

int n,t,k,m;

void solve() {
    int x,a,b;
    cin >> m >> x >> a >> b;
    int ma = a + m, mi = max(b - m / x,0ll);
    double ans = max((double) ma / (ma + b), (double)(a + m % x) / (m % x + a + mi));
    printf("%.9lf\n",ans);
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    int Ke_scholar = 1;
    cin >> Ke_scholar;
    while(Ke_scholar--)
        solve();
    return 0;
}

C. 饮茶

先假设每天都出去玩。这样,如果到某天来不及了,我只能放弃之前某天出去玩,此时显然放弃浪费时间越多的越好。因此,从前到后维护当前还能放弃的时间差最大堆,需要的时候弹掉最大的直到满足条件,最后输出堆的大小。
这里我用的是优先队列,不过都是一个道理

#include <bits/stdc++.h>
#define endl '\n'
#define int long long
#define  inf 0x3f3f3f3f

using namespace std;
const int N = 2e3 + 10;

typedef pair<int,int> PII;
map<int, int > mp;
int n,m,t,k,c;
int mod,ans;
void solve()
{
    cin >> n;
    priority_queue<int> T;
    int a,b;
    int ans = n;
    int sumtime = 0;
    for(int i = 0;i < n;i++){
        cin >> t >> a >> b;
        if(a > b)
            T.push(a - b);
        sumtime += b - t;
        while(sumtime < 0){
            if(T.empty()){
                cout << -1 << endl;
                return ;
            }
            sumtime += T.top();
            T.pop();
            ans --;
        }
    }
    cout << ans << endl;
}
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    int Ke_scholar = 1;
    //cin >> Ke_scholar;
    while(Ke_scholar--)
        solve();
    return 0;
}