2022ICPC西安站 C,F,G,J

213 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第8天,点击查看活动详情

C - Clone Ranran

  • 中文大意

现在有c个活动需要举办将现有的活动复制一次需要花费a时间增加一个需要b时间,问我们举办c个活动至少需要多长时间

  • 解法

我们发现如果执行复制操作我们其实最多能执行的次数不超过32次,但是b操作的可执行次数最多到达了1e9次,所以我们选择去枚举最后使用a操作的次数,然后二分b操作的次数即可

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

void solve() {
    ll a, b, c; scanf("%lld %lld %lld", &a, &b, &c);
    ll res = 1e18;
    for(int i = 0; i < 32; i++) {
        int l = 1, r = c;
        auto check = [&](int x) {
            ll ans = b * x;
            int n = x;
            int cnt = 0;
            while(n < c && cnt < i) {
                n *= 2;
                ans += a;
                cnt ++;
            }
            if(n >= c) {
                res = min(res, ans);
                return true;
            }else return false;
        };
        while( l <= r) {
            int mid = l + r >> 1;
            if(check(mid)) r = mid - 1;
            else l = mid + 1;
        }
    }
    printf("%lld\n", res);
}

int main() {
    int T; scanf("%d", &T);
    while(T--) solve();
}

F - Hotel

  • 中文大意

有n个队伍参加比赛每个队伍有三个队员,现在需要给他们安排房间有单人房和双人房,只有同队并且性别相同的才能住一间双人房,否则只能单独住单人房

  • 解法

对每一队进行枚举即可

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
char s[10];
void solve() {
    int n, c1, c2; scanf("%d %d %d",&n, &c1, &c2);
    c2 = min(c2, 2*c1);
    c1 = min(c1 ,c2);
    // printf("%d %d\n",c1, c2);
    vector<int> a(26,0);
    ll res = 0;
    for(int i = 1; i <= n; i++) {
        scanf("%s", s + 1);
        for(int j = 1; j <= 3; j++) a[s[j] - 'A'] ++;
        for(int j = 0; j < 26; j++) {
        // printf("%d\n",a[i]);
        res += a[j] / 2 * c2;
        if(a[j] & 1) res += c1;
        a[j] = 0;
        }
    }
    
    printf("%lld\n",res);
}

int main() {
    // int T; scanf("%d", &T);
    // while(T--) 
        solve();
}

G - Perfect Word

  • 中文大意

给你n个字符串,问最长长度所有字串都出现过的字符串是多少

  • 解法

我们会发现如果长度为x的符合那么长度为x - 1的也符合所以我们对所有的字符串进行排序从小到大进行判断

#include <bits/stdc++.h>
using namespace std;

int n;
string s[100005];
set<string> S;
int main()
{
	ios::sync_with_stdio(false);
	cin>>n;
	for(int i=0;i<n;i++) cin>>s[i];
	sort(s,s+n,[](const string &a,const string &b){
		return a.size()<b.size();
	});
	int res=0;
	for(int i=0;i<n;i++)
	{
		if(s[i].size()==1 || (S.count(s[i].substr(0,s[i].size()-1)) && S.count(s[i].substr(1))))
		{
			S.insert(s[i]);
			res=max(res,(int)s[i].size());
		}
	}
	cout<<res<<endl;
	return 0;
}

J - Strange Sum

签到题
从数组中选取最多两个数之和问是多少

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int a[100010];
void solve() {
    int n; scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d",a + i);
    sort(a + 1,a + 1 + n,[](int a,int b){
        return a > b;
    });
    int res = 0;
    for(int i = 1; i <= 2; i ++){
        res = max(res, res + a[i]);
    }
    printf("%lld\n",res);
}

int main() {
    // int T; scanf("%d", &T);
    // while(T--) 
        solve();
}