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(dpi−1,j,dppre,j−1+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 k≥⌈32⋅n⌉ 的序列 a a a ,使之满足以下条件:
- a i > a i − 1 a_i \gt a_{i - 1} ai>ai−1;
- 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(ai−1,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}
gi∗gi+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=gi−1∗giai+1=gi∗gi+1
显然,
g
i
−
1
g_{i - 1}
gi−1 和
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;
}