Codeforces Round 969 (Div. 2) ABCD

A题:Dora's Set

思路

贪心地想,如果可以的话,我们直接全用连续的3个,这样就能实现最多

但是给出的样例

1 1000

250

说明了有连续的三个不符合的情况

先考虑连续两个的情况,是一定符合gcd(x, x+1)=1的

因为x+1-x=1

(你可能觉得我写的抽象,但这是裴蜀定理)

那么对于x,x+1,x+2

当且仅当x为奇数的时候,可以符合题意

        因为当x为奇数的时候,x+1和x+2是符合题意的

        那么就是考虑x和x+2了,可以证明的是,当x为奇数的时候,存在a和b两个系数使得(x+2)*a - x*b的值为1,因此可以使得gcd为1

而x为偶数的时候,x,x+1,x+2不能满足,但我们可以贪心,只要x,x+1,x+3就可以满足题意了

代码

inline void solve() {
     int l, r; cin >> l >> r;
     int ans = 0;
     for (int i = l; i <= r; i ++ ) {
        if (i & 1) {
            if (i + 2 <= r) ans += 1;
            i += 2;
        }else {
            if (i + 3 <= r) ans += 1;
            i += 3;
        }
     }
     cout << ans << endl;
	 return;
}

B题:Index and Maximum Value

思路

 仔细想下,这个更改值的操作,我们只用管最大值就行了

代码

inline void solve() {
     int n, m; cin >> n >> m;
     ll maxv = 0;
     for (int i = 1; i <= n; i ++ ) {
        ll x; cin >> x;
        maxv = max(maxv, x);
     }
     for (int i = 1, l, r; i <= m; i ++ ) {
        char op; cin >> op;
        cin >> l >> r;
        if (maxv >= l && maxv <= r) maxv = maxv + (op == '+' ? 1 : -1);
        cout << maxv << " \n"[i == m];
     }
	 return;
}

C题:Dora and C++

思路

如果a和b相等的话

        我们可以先将这些值都模上a,然后sort一遍。

        此后我们枚举哪个数作为最小值即可。

不相等

        相等的话,我们就只用考虑一个数的影响,而两个数也是这样的

        注意到题目只存在加,不存在减,但是其实是一样的,你给其他数加上,就相当于给这个数减去

        因为ax+by=gcd(a,b)总存在,因此我们就可以用gcd拿来进行a和b相等时候的操作

代码

inline void solve() {
     ll n, a, b; cin >> n >> a >> b;
     a = gcd(a, b);
	 vector<ll> c(n + 1);
	 for (int i = 1; i <= n; i ++ ) cin >> c[i], c[i] %= a;
	 sort(c.begin() + 1, c.end());
	 ll res = c[n] - c[1];
	 for (int i = 2; i <= n; i ++ ) {
		res = min(res, c[i - 1] + a - c[i]);
	 }
	 cout << res << endl;
	 return;
}

D题:Iris and Game on the Tree

思路

答案只与根节点和叶节点是否相等有关

证明:

        无论这个路径上是什么

        都可以压缩为10101,101这种的形式(111110101==10101)

        而中间的那么一大块其实+1和-1相互都抵消掉了

        所以剩下来的只是1,10,0,01

        不相等的时候,可以对答案产生一的贡献

那么剩下来的就是分类讨论了

如果根节点已知,按题意模拟即可

未知的情况下,直接对根节点进行赋值的话,可能会亏一个(样例4)

如果叶节点0和1的数量不一样多,那么取大的直接对根节点赋值(这样不会亏)

但一样多的话,要进行讨论,

其实对于叶节点,两者足够聪明的情况下是101或者010又或是0101这样来的,奇数的情况关键在于能否使得自己最后一个赋值根节点(这个我们只要看有没有其他的?可以划水即可)

偶数的情况其实都是定的,叶节点最多一半

代码

inline void solve() {
     int n; cin >> n;
     vector<vector<int>> e(n + 1);
     for (int i = 1; i < n; i ++ ) {
        int u, v; cin >> u >> v;
        e[u].push_back(v), e[v].push_back(u);
     }
     int cnt[3] = {}, cnt4 = 0;
     string v; cin >> v;
     v = ' ' + v;
     for (int i = 2; i <= n; i ++ ) {
        if (e[i].size() == 1) {
            if (v[i] == '1') cnt[1] += 1;
            else if (v[i] == '0') cnt[0] += 1;
            else cnt[2] += 1;
        }else if (v[i] == '?') cnt4 += 1;
     }
     if (v[1] != '?') {
        cout << cnt[(v[1] - '0') ^ 1] + (cnt[2] + 1) / 2 << endl;
     }else {
        if (cnt[0] == cnt[1]) {
            cout << cnt[0] + cnt[2] / 2 + ((cnt4 & 1) && (cnt[2] & 1)) << endl;
        }else {
            cout << max(cnt[0], cnt[1]) + cnt[2] / 2 << endl;
        }
     }
	 return;
}

         

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值