AtCoder Regular Contest 156题解

A - Non-Adjacent Flip

这道题有点思维题的意思

首先单数肯定不行

如果是大于4的偶数那么肯定都可以(这点也要想明白)

因为1111的话,1和3配,2和4配,怎样都能配好的

接下来讨论下剩下的情况

n=3的时候,只要中间不是1都可以

其他时候我们只要把下标存起来,稍微判断就可以

代码如下

#include <bits/stdc++.h>
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair<int,int>
#define et  cout<<'\n'
#define xx first
#define yy second
using namespace std;   
const int N=1e6+10; 

void solve(){
	int n;
    cin >> n;
    string s;
    cin >> s;
    int cnt = count(s.begin(), s.end(), '1');
    if (cnt % 2 == 1) {
        cout << -1 << "\n";
        return;
    }
    if (cnt == 0) {
        cout << 0 << "\n";
        return;
    }
    if (cnt >= 4) {
        cout << cnt / 2 << "\n";
        return;
    }
    if (n == 3) {
        if (s[1] == '1') {
            cout << -1 << "\n";
        } else {
            cout << 1 << "\n";
        }
        return;
    }
    vector<int> pos;
    for (int i = 0; i < n; i++) {
        if (s[i] == '1') {
            pos.push_back(i);
        }
    }
    if (pos[1] - pos[0] > 1) {
        cout << 1 << "\n";
        return;
    }
    if (n == 4 && pos[0] == 1) {
        cout << 3 << "\n";
    } else {
        cout << 2 << "\n";
    }
}
signed main()
{
	ios::sync_with_stdio(0);
   	cin.tie(0);
	int T;
	cin>>T;
	while(T--){
		solve();
	}
}

B - Mex on Blackboard

给定N个元素的数组A,每次操作,你可以从数组种选出任意个元素,然后向数组中加入这些

元素的MEX

问k次之后九二一得到多少种不同的数组

枚举写上去的最大数x,计算写上这个数字至少需要几次有贡献的操作,对剩下的操作数求组合数

#include <bits/stdc++.h>
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair<int,int>
#define et  cout<<'\n'
#define xx first
#define yy second
using namespace std;   
const int N=1e6+10; 
int n, k;
int a[N];
int cnt[N];
const int mod = 998244353;
int qpow(int a, int b){
    int ans = 1;
    while(b){
        if(b & 1){
            ans *= a;
            ans %= mod;
        }
        a *= a;
        a %= mod;
        b /= 2;
    }
    return ans;
}
int fc[N];
int gc[N];
void prep(){
    fc[0] = gc[0] = 1;
    for(int i=1;i<N;i++){
        fc[i] = (fc[i - 1] * i) % mod;
        gc[i] = qpow(fc[i], mod - 2);
    }
}
 
int C(int n, int k){
    int ans = fc[n];
    ans *= gc[k];
    ans %= mod;
    ans *= gc[n - k];
    ans %= mod;
    return ans;
}
 
void solve(){
    cin >> n >> k;
    for(int i=1;i<=n;i++){
        cin >> a[i];
        cnt[a[i]]++;
    }
 
    vector<int> holes;
    for(int i=0;i<N;i++){
        if(!cnt[i]) holes.pb(i);
    }
    prep();
    int ans = 0;
    if(holes[0] != 0){
        ans += C(holes[0] + k - 1, holes[0] - 1);
        ans %= mod;
    }
    for(int i=0;i<k;i++){
        int nxt = holes[i + 1];
        ans += C(nxt + (k - (i + 1)) - 1, nxt - 1);
        ans %= mod;
    }
    cout << ans << "\n";
}
signed main(){
    solve();
}


C - Tree and LCS

给定一棵N个节点的树T,编号为1-N,定义排列P与T的相似度为

对于T一个不重复路径(x1,x2,x3,,,,xn),路径相似度为(x1,x2....xn)与(Px1,Px2,Px3,,,,Pxn)的最长公共子序列长度

P与T的相似度为T中所有路径相似度的最大值

请构造一个排列P,使其与T相似度最小

构造题,两T在BFS序上的相邻节点,即可将相似度锁定为 1 。

#include <bits/stdc++.h>
#define int long long
#define pb push_back
#define fer(i,a,b) for(int i=a;i<=b;++i)
#define der(i,a,b) for(int i=a;i>=b;--i)
#define all(x) (x).begin(),(x).end()
#define pll pair<int,int>
#define et  cout<<'\n'
#define xx first
#define yy second
using namespace std;   
const int N = 5005;
int n, d[N], p[N], que[N], l, r;
vector<int> e[N];
signed main() {
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> n;
    for (int i = 1; i < n; ++i) {
        int u, v;
        cin >> u >> v;
        e[u].push_back(v);
        e[v].push_back(u);
        ++d[u], ++d[v];
    }
 
    l = 1;
    for (int i = 1; i <= n; ++i)
        if (d[i] == 1) que[++r] = i;
    while (l <= r) {
        int u = que[l++];
        for (auto v : e[u]) {
            if (d[v] > 1 && --d[v] == 1) {
                que[++r] = v;
            }
        }
    }
    iota(p + 1, p + n + 1, 1);
    for (int i = 1; i < n; i += 2)
        swap(p[que[i]], p[que[i + 1]]);
    for (int i = 1; i <= n; ++i) 
        cout << p[i] << " \n"[i == n];
 
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值