Codeforces Round 958 (Div. 2) (A-D)

A. Split the Multiset

考虑看成是n个1,每次最多合并其中k个数,最少多少次能合并为一个数

#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define rep(x,a,b) for(int x=a;x<=b;x++)
#define pre(x,a,b) for(int x=a;x>=b;x--)
#define ac puts("Yes")
#define wa puts("No")
#define int long long
// #define endl "\n"
#define pb push_back
#define pii pair<ll, ll>
#define de cout<<1;
#define mem(a,x) memset(a,x,sizeof a)
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define ull unsigned long long
#define eps 1e-6
#define RI register int
#define CI const int&
using namespace std;
const int mod=1e9 + 7;
const int N = 1e6 + 10;
int n, k, cnt;
void solve()
{
	cin >> n >> k;
    cnt = 0;
    if(n == 1) cout << 0 << endl;
    else
    {
        int cnt = 0;
        while(n > 1)
        {
            cnt ++ ;
            n -= (k - 1);
        }
        cout << cnt << endl;
    }
}
signed main()
{
	IOS;
	int t;
	t = 1;
	cin >> t;
	while(t -- )
	{
		solve();
	}
	return 0;
}

B. Make Majority

先合并连续的0,然后看此时1和0哪个多即可

#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define rep(x,a,b) for(int x=a;x<=b;x++)
#define pre(x,a,b) for(int x=a;x>=b;x--)
#define ac puts("Yes")
#define wa puts("No")
#define int long long
// #define endl "\n"
#define pb push_back
#define pii pair<ll, ll>
#define de cout<<1;
#define mem(a,x) memset(a,x,sizeof a)
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define ull unsigned long long
#define eps 1e-6
#define RI register int
#define CI const int&
using namespace std;
const int mod=1e9 + 7;
const int N = 1e6 + 10;
int n, k, cnt, m;
void solve()
{
	cin >> n;
    string s;
    cin >> s;
    s = " " + s;
    string t;
    t += " ";
    rep(i, 1, n)
    {
        if(s[i] == '1') t += '1';
        else 
        {
            t += '0';
            while(i + 1 <= n && s[i + 1] == '0') i ++ ;
        }
    }
    m = t.size() - 1;
    int c1 = 0, c0 = 0;
    rep(i, 1, m) if(t[i] == '1') c1 ++ ; else c0 ++ ;
    if(c1 <= c0) cout << "No" << endl;
    else cout << "Yes" << endl;
}
signed main()
{
	IOS;
	int t;
	t = 1;
	cin >> t;
	while(t -- )
	{
		solve();
	}
	return 0;
}

C. Increasing Sequence with Fixed OR

以为是与运算,且要构造的数组严格递增,那么最后一个位置一定可以放n,为了保证严格单调递增,直接低位枚举n的二进制位即可,假设当前枚举到第i位时n的二进制位为1,那么把n-(1<<i)加入答案即可。

#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define rep(x,a,b) for(int x=a;x<=b;x++)
#define pre(x,a,b) for(int x=a;x>=b;x--)
#define ac puts("Yes")
#define wa puts("No")
#define int long long
// #define endl "\n"
#define pb push_back
#define pii pair<ll, ll>
#define de cout<<1;
#define mem(a,x) memset(a,x,sizeof a)
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define ull unsigned long long
#define eps 1e-6
#define RI register int
#define CI const int&
using namespace std;
const int mod=1e9 + 7;
const int N = 1e6 + 10;
int n;
void solve()
{
	cin >> n;
    vector<int>ans;
    ans.push_back(n);
    if(n - lowbit(n) == 0)
    {
        cout << 1 << endl << n << endl;
        return;
    }
    rep(i, 0, 60)
    {
        if(n >> i & 1) ans.push_back(n - (1ll << i));
    }
    reverse(ans.begin(), ans.end());
    cout << ans.size() << endl;
    for(auto i : ans) cout << i << " ";
    cout << endl;
}
signed main()
{
	IOS;
	int t;
	t = 1;
	cin >> t;
	while(t -- )
	{
		solve();
	}
	return 0;
}

D. The Omnipotent Monster Killer

可以看出在经过一些轮操作之后,整个树上的怪物都会被杀死,由于不能选择相邻的点,那么可以想到,当前轮次没有被杀死的怪物,它的父亲或儿子节点上的怪兽就应该有至少一个被杀死,那么可以看出每次大约会杀死剩下节点数的一半的怪物,那么最多需要log轮次即可杀死所有怪物,log(3e5)大约20轮,因此考虑树形dp,f[i][j]表示i的子树的怪物都被杀死,且i在j轮被杀死时,所造成的最小伤害,那么儿子节点只要和当前枚举的轮次不相等那么都可以选,从中选择最小值暴力转移即可。

#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define rep(x,a,b) for(int x=a;x<=b;x++)
#define pre(x,a,b) for(int x=a;x>=b;x--)
#define ac puts("Yes")
#define wa puts("No")
#define int long long
#define endl "\n"
#define pb push_back
#define pii pair<ll, ll>
#define de cout<<1;
#define mem(a,x) memset(a,x,sizeof a)
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define ull unsigned long long
#define eps 1e-6
#define RI register int
#define CI const int&
using namespace std;
const int mod=1e9 + 7;
const int N = 1e6 + 20;
int n;
vector<int>p[N];
int a[N], dp[N][21], f[N][21];
void dfs(int u, int fa)
{
    int flag = 0;
    for(auto j : p[u])
    {
        if(j == fa) continue;
        dfs(j, u);
        flag = 1;
    }
    if(!flag) rep(i, 1, 20) f[u][i] = dp[u][i];
    else
    {
        rep(x, 1, 20) f[u][x] = dp[u][x];
        for(auto j : p[u])
        {
            if(j == fa) continue;
            int cnt = 0;
            rep(x, 1, 20)
            {
                cnt = 1e18;
                rep(y, 1, 20)
                {
                    if(x == y) continue;
                    cnt = min(cnt, f[j][y]);
                }
                f[u][x] += cnt;
            }
        }
    }
}
void solve()
{
	cin >> n;
    rep(i, 1, n) p[i].clear();
    rep(i, 1, n) cin >> a[i];
    rep(i, 1, n)
    rep(j, 1, 20)
    {
        dp[i][j] = a[i] * j;
        f[i][j] = 1e18;
    }
    rep(i, 1, n - 1)
    {
        int u, v;
        cin >> u >> v;
        p[u].push_back(v);
        p[v].push_back(u);
    }
    dfs(1, 0);
    int ans = 1e18;
    rep(i, 1, 20) ans = min(ans, f[1][i]);
    cout << ans << endl;
}
signed main()
{
	IOS;
	int t;
	t = 1;
	cin >> t;
	while(t -- )
	{
		solve();
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值