我是靠谱客的博主 顺心猎豹,最近开发中收集的这篇文章主要介绍Codeforces Round #757 (Div. 2)Codeforces Round #757 (Div. 2),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

Codeforces Round #757 (Div. 2)

problem: (C ) Divan and bitwise operations

刚开始在写拆位,然后对于每一位有若干区间不存在,再把这些区间合并,算一个总长度,剩下的就是含有这位的数,再套个组合数

写一半边上妹妹说乱猜就过了然后回过头来模样例,112除以16怎么是7啊可恶,就猜了下就过了

先说结论:把读入的每个数或起来然后乘上2的n-1次

关于证明:还是拆位考虑,对于第i位如果存在一个位置是1,不考虑这个位置,剩下长度为n - 1的数的subsequence是 2 n − 1 2^{n - 1} 2n1,并且对于每个subsequence再加上这个位置都可以唯一确定一个xor贡献为(1 << i)的方案:当其余位置xor和为0时,取这位的1;xor为(1 << i) 时,不取这位的1 。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const ll N = 1e6 + 10;
const ll M = 40;
const ll mod = 1e9 + 7;
const ll inf = 0x3f3f3f3f;

struct node {
    ll l, r;
};
vector<node> vec[M];

ll qpow(ll x, ll n) {
    ll res = 1;
    while (n) {
        if (n & 1) res = res * x % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return res;
}

signed main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);

    ll T;
    cin >> T;
    while (T--) {

        ll n, m;
        cin >> n >> m;
        ll ans = 0;
        for (ll i = 0; i < m; ++i) {
            ll l, r, x;
            cin >> l >> r >> x;
            ans = ans | x;
        }

        ans = ans % mod;
        ans = ans * qpow(2, n - 1) % mod;
        cout << ans << endl;
    }
    return 0;
}

problem: (D1) Divan and Kostomuksha (easy version)

考虑直接构造一个gcd序列

满足每个数是前一个数的约数,考虑dp转移,先对于每个数分解(将它的每个约数的num++,反过来也就是对于每个数将它本身的贡献加到它的每个倍数上面)

构造的gcd序列是有点像阶梯那样的(什么破比喻)d1d1…d1d2d2…d2d3d3…d3…,
记num[i] := i 的倍数有多少个

dp[i] := 以 i 开头的数列的最大值

从后往前dp, d p [ i ] = m a x j ∣ i { d p [ i ] , n u m [ i ] ∗ ( i − j ) + d p [ j ] } dp[i] = max _{j| i} {dp[i], num[i] * (i - j) + dp[j]} dp[i]=maxji{dp[i],num[i](ij)+dp[j]} // 大概想的是按层算贡献

时间复杂度:计算num这里 O ( M l o g M ) O(M log M) O(MlogM) dp这里 O ( M l o g M ) O(M log M) O(MlogM) , 所以一共也是 O ( M l o g M ) O(M log M) O(MlogM)

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const ll N = 5e6 + 10;
ll a[N], dp[N], num[N];

signed main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);

    ll n;
    cin >> n;
    for (ll i = 1; i <= n; ++i) {
        cin >> a[i];
        ++num[a[i]];
    }

    for (ll i = 1; i < N; ++i) {
        for (ll j = i << 1; j < N; j += i) {
            num[i] += num[j];
        }
    }

    dp[1] = num[1];
    for (ll i = 1; i < N; ++i) {
        for (ll j = 2; j * i < N; ++j) {
            dp[i * j] = max(dp[i * j], dp[i] + (j * i - i) * num[i * j]);
        }
    }

    ll ans = 0;
    for (ll i = 1; i < N; ++i) {
        ans = max(ans, dp[i]);
    }
    cout << ans << endl;

    return 0;
}

problem: (D2) Divan and Kostomuksha (hard version)

进行一个优化,可以使得gcd数列里面每一项都是前一项刚好除掉一个素数,将合数拆开中间以实际不存在的素数作为跳板(因为没出现算贡献的时候是0)

即将gcd 6666111表示成 6(4) 3(0) 1(3) 括号内为数的个数

想法参考埃氏筛,于是这部分的复杂度就变成了 O ( M l o g l o g M ) O(MloglogM) O(MloglogM) 几乎 O ( M ) O(M) O(M)

先将素数都筛出来然后对于每个数枚举他的因子的时候 枚举中间的倍数 并且这个倍数是素数

前面num的部分可以用类似的方法参考狄利克雷前缀和,高位前缀和之类的做也是 O ( M l o g l o g M ) O(MloglogM) O(MloglogM), 或者对于每个数分解把他每个数位置的因子加上去

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const ll N = 2e7 + 10;
ll a[N], dp[N], num[N];

ll primes[N], cnt = 0;
bool st[N];

void sieve() {
    cnt = 0;
    for (ll i = 2; i < N; ++i) {
        if (!st[i]) primes[++cnt] = i;
        for (ll j = 1; primes[j] * i < N; ++j) {
            st[primes[j] * i] = 1;
            if (i % primes[j] == 0) break;
        }
    }
}

signed main() {
    ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);

    sieve();

    ll n;
    cin >> n;
    for (ll i = 1; i <= n; ++i) {
        cin >> a[i];
        ++num[a[i]];
    }

    for (ll i = 1; i <= cnt; ++i) {
        for (ll x = N / primes[i]; x; --x) {
            num[x] += num[x * primes[i]];
        }
    }

//    for (ll i = 1; i < N; ++i) {
//        for (ll j = i << 1; j < N; j += i) {
//            num[i] += num[j];
//        }
//    }

    dp[1] = num[1];
    for (ll i = 1; i < N; ++i) {
//        for (ll j = 2; j * i < N; ++j) {
//            dp[i * j] = max(dp[i * j], dp[i] + (j * i - i) * num[i * j]);
//        }
        for (int k = 1; i * primes[k] < N; ++k) {
            dp[i * primes[k]] = max(dp[i * primes[k]], dp[i] + (i * primes[k] - i) * num[i * primes[k]]);
        }
    }

    ll ans = 0;
    for (ll i = 1; i < N; ++i) {
        ans = max(ans, dp[i]);
    }
    cout << ans << endl;

    return 0;
}

最后

以上就是顺心猎豹为你收集整理的Codeforces Round #757 (Div. 2)Codeforces Round #757 (Div. 2)的全部内容,希望文章能够帮你解决Codeforces Round #757 (Div. 2)Codeforces Round #757 (Div. 2)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(43)

评论列表共有 0 条评论

立即
投稿
返回
顶部