gym 102956补题

gym 102956

链接:2020-2021 Winter Petrozavodsk Camp, Belarusian SU Contest (XXI Open Cup, Grand Prix of Belarus)

D - Bank Security Unification

题意

n n n 个路由器,第 i i i 个路由器的的频度是 f i f_i fi ,假设有 k k k 个路由器 i 1 , i 2 , … , i k i_1, i_2, …, i_k i1,i2,,ik 开着,那么此时的网络安全系数的值是 ∑ j = 1 k a i j \sum_{j = 1}^k a_{i_j} j=1kaij 。问网络安全系数的最大值是?

思路

背包dp, d p i , j dp_{i, j} dpi,j表示处理到 i i i ,打开 j j j 个的最大安全系数。

处理到 f i f_i fi 时的转移方程式:
d p i , j = m a x ( d p i − 1 , j , d p p r e , j − 1 + f p r e & f i ) dp_{i, j} = max(dp_{i - 1, j}, dp_{pre, j - 1} + f_{pre} \& f_i) dpi,j=max(dpi1,j,dppre,j1+fpre&fi)
这里的 p r e pre pre 表示上一个被选中的数。但是数据范围 1 e 6 1e6 1e6 ,所以改成滚动数组减少一维。

最终的转移方程:( p r e pre pre 的可能值可以通过对 a i a_i ai 逐位运算进行枚举,这个在代码中有所体现)
d p i = m a x ( d p i , d p p r e + f p r e & f i ) dp_i = max(dp_i, dp_{pre} + f_{pre} \& f_i) dpi=max(dpi,dppre+fpre&fi)

代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 2e6 + 9;
const ll MOD = 1e9 + 7;

ll dp[N];
ll a[N];
ll pre[N];

int main()
{
    int n;
    scanf("%d", &n);
    for(int i = 1; i <= n; i++)
    {
        scanf("%lld", a + i);
    }
    ll ans = 0;
    for(int i = 1; i <= n; i++)
    {
        for(int j = 0; j <= 50; j++)
        {
            if(a[i] & (1ll << j))
            {
                dp[i] = max(dp[i], dp[pre[j]] + (a[pre[j]] & a[i]));
                pre[j] = i;
            }
        }
        ans = max(ans, dp[i]);
        dp[i] = ans;
    }
    printf("%lld\n", ans);
    return 0;
}

I - Binary Supersonic Utahraptors

题意

A有 n n n 个牌, B有 m m m 个牌,其中一些是红的一些是黄的。进行 k k k 次交换,第 i i i 次A给B s i s_i si 张牌,B再在当前的所有牌中给A s i s_i si 张牌。最终得分为A的黄牌数-B的红牌数的绝对值,A要使之尽可能大,B要使之尽可能小。问最终得分?

思路

就是A的|初始黄牌数-B的初始红牌数|,可以证明之后其实怎么改都是不会改变这两者差的绝对值。

代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 2e6 + 9;
const ll MOD = 1e9 + 7;

int main()
{
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
    int ans = 0;
    for(int i = 0, tmp; i < n; i++)
    {
        scanf("%d", &tmp);
        if(tmp == 0)
            ans++;
    }
    for(int i = 0, tmp; i < m; i++)
    {
        scanf("%d", &tmp);
        if(tmp)
            ans--;
    }
    printf("%d\n", abs(ans));
    return 0;
}

M - Brilliant Sequence of Umbrellas

题意

给定数字 n n n ,要求你构造长度 k ≥ ⌈ 2 3 ⋅ n ⌉ k \geq \lceil \frac{2}{3} · n \rceil k32n 的序列 a a a ,使之满足以下条件:

  1. a i > a i − 1 a_i \gt a_{i - 1} ai>ai1
  2. g c d ( a i , a i + 1 ) > g c d ( a i − 1 , a i ) gcd(a_i, a_{i + 1}) \gt gcd(a_i - 1, a_i) gcd(ai,ai+1)>gcd(ai1,ai)

思路

g i = g c d ( a i , a i + 1 ) g_i = gcd(a_i, a_{i + 1}) gi=gcd(ai,ai+1) ,我们又要使 a i a_i ai 的值尽可能小这样才能增加长度,所以必然有 g i ∗ g i + 1 = a i + 1 g_i * g_{i + 1} = a_{i + 1} gigi+1=ai+1。由此我们得到:
g c d ( a i , a i + 1 ) = g i a i = g i − 1 ∗ g i a i + 1 = g i ∗ g i + 1 gcd(a_i, a_{i + 1}) = g_i\\a_i = g_{i - 1} * g_i\\ a_{i + 1} = g_i * g_{i + 1} gcd(ai,ai+1)=giai=gi1giai+1=gigi+1
显然, g i − 1 g_{i - 1} gi1 g i + 1 g_{i + 1} gi+1 要互质。根据这个性质去构造即可。

代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define PI acos(-1)
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
const int N = 1e6 + 9;
const ll MOD = 1e9 + 7;

ll gcd[N];

int main()
{
    ll n;
    scanf("%lld", &n);
    gcd[0] = 1;
    gcd[1] = 2;
    gcd[2] = 3;
    int kmin = 2.0 / 3.0 * sqrt((double)n) + 1;
    for(int k = 3; k < kmin; k++)
    {
        ll x = gcd[k - 1] + 1;
        while(__gcd(gcd[k - 2], x) != 1)
        {
            x++;
        }
        gcd[k] = x;
    }
    printf("%d\n1", kmin);
    for(int i = 0; i < kmin - 1; i++)
    {
        printf(" %lld", gcd[i] * gcd[i + 1]);
    }
    printf("\n");
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值