牛客练习赛 121

牛客练习赛 121

A 小念吹气球

分析

打标记统计一下数量即可

代码

点击查看代码
void solve () {
    int n; string s;
    cin >> n >> s;
    ll cn = 0;
    map<char, bool> mp;
    for (int i = 0; i < n; i ++) {
    	if (!mp[s[i]]) {
    		cn += 2;
    		mp[s[i]] = true;
    	} else {
    		cn ++;
    	}
    }
    cout << cn << endl;
    return ;
}

B You Brought Me A Gentle Breeze on the Field

分析

首先\(n = 1\)时先手必败,第二种情况是\(2 <= n <= m + 1\),这种情况下先手必胜,因为先手可以直接拿n - 1个,第三种情况则是\(n >= m + 2\),此时有连续机会的人必胜,因为无论初始局面的先手胜负情况如何,其一定可以通过连续机会调换先后手顺序,使自己必胜

代码

点击查看代码
void solve () {
    int n, m, k;
    cin >> n >> m >> k;
    if (n == 1) cout << "YangQiShaoNian" << endl;
    else if (n >= 2 && n <= m + 1) cout << "XiaoNian" << endl;
    else {
    	if (k == 0) {
    		cout << "XiaoNian" << endl;
    	} else {
    		cout << "YangQiShaoNian" << endl;
    	}
    }
    return ;
}

C 氧气少年的水滴 2

分析

模拟即可,详见代码

代码

点击查看代码
void solve () {
    int n, m;
    cin >> n >> m;
    vector<int> a(n + 1);
    for (int i = 1; i <= n; i ++) cin >> a[i];
    if (a[m] < 9) {
    	cout << 0 << ' ' << 0 << endl;
    } else {
    	ll cn0 = 1, cn1 = 1, l = m - 1, r = m + 1;
    	while (true) {
    		bool fl = false;
    		while (l >= 1 && cn0 > 0 && a[l] < 10) fl = true, a[l] ++, cn0 --;
    		if (a[l] == 10) cn0 ++, cn1 ++, l --;
    		while (r <= n && cn1 > 0 && a[r] < 10) fl = true, a[r] ++, cn1 --;
    		if (a[r] == 10) cn1 ++, cn0 ++, r ++;	
    		if (!fl) break;
    	}
    	cout << cn0 <<  ' ' << cn1 << endl;
    }
    return ;
}

D 氧气少年的 LCM

分析

可知LCM一定是GCD的倍数,代码中cn即是这个量。然后二进制拆分即可,先把要用到的二进制数全都算出,然后按位加即可

代码

点击查看代码
struct Node{
	ll op, a, b;
};

void solve () {
    ll x, y; cin >> x >> y;
    if (x > y) swap(x, y);
    ll g = gcd(x, y);
    vector<Node> ans;
	ll cn = x * y / g / g;
    ans.pb({1, x, y});
    ans.pb({1, x, y});
    for (ll i = 1; (cn >> i) != 0; i ++) {
    	ans.pb({2, (1ll << (i - 1)) * g, (1ll << (i - 1)) * g});
    	ans.pb({2, (1ll << (i - 1)) * g, (1ll << (i - 1)) * g});
    }
    ll nw = 0;
    for (ll i = 0; (cn >> i) != 0; i ++) {
    	if (cn >> i & 1) {
    		if (nw == 0) {
    			nw = (1ll << i) * g;
    			continue;
    		}
    		ans.pb({2, nw, (1ll << i) * g});
    		nw += (1ll << i) * g;
    	}
    }
    cout << ans.size() << endl;
    for (auto node : ans)
    	cout << node.op << ' ' << node.a << ' ' << node.b << endl;
    return ;
}

D 氧气少年逛超市 3

分析

简单线性dp

代码

点击查看代码
void solve () {
    int n, m, k;
    cin >> n;
    vector<int> p(n + 1);
    for (int i = 1; i <= n; i ++) cin >> p[i];
    cin >> m;
    vector<int> x(m + 1);
    for (int i = 1; i <= m; i ++) cin >> x[i];
    cin >> k;
    vector<int> y(k + 1);
    for (int i = 1; i <= k; i ++) cin >> y[i];
    sort(p.begin() + 1, p.end(), greater<int>());
    sort(x.begin() + 1, x.end());
    sort(y.begin() + 1, y.end(), greater<int>());
    vector<vector<double>> f(n + 1, vector<double> (n + 1));
    for (int i = 0; i <= n; i ++)
    	for (int j = 0; j <= n; j ++) 	
    		f[i][j] = 1e9;
    f[0][0] = 0;
    for (int i = 1; i <= n; i ++) {
    	for (int j = 0; j <= min(i, m); j ++) {
    		if (j != 0) 
    			f[i][j] = min(f[i][j], f[i - 1][j - 1] + (double)p[i] * x[j] / 100.0);
    		if (i > j + k)
    			f[i][j] = min(f[i][j], f[i - 1][j] + p[i]);
    		else
    			f[i][j] = min(f[i][j], f[i - 1][j] + max(0, p[i] - y[i - j]));
    	}
    }
    double ans = 1e9;
    for (int i = 0; i <= m; i ++) ans = min(ans, f[n][i]);
    cout << ans << endl;
    return ;
}
posted @ 2024-01-27 10:31  ComistryMo  阅读(48)  评论(0)    收藏  举报