2019-2020 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了2019-2020 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)相关的知识,希望对你有一定的参考价值。
D - Dividing By Two
给定数 A , B A,B A,B,每次可以把 A A A加 1 1 1,或者把 A / 2 A/2 A/2(要求 A A A为偶数)
问最少多少次可以把 A A A变成 B B B
考虑把 B B B变成 A A A,相当于每次只能乘以 2 2 2或让自己减 1 1 1
设共执行 k 1 k_1 k1次乘 2 2 2操作, k 2 k_2 k2次减 1 1 1操作
A = B ∗ 2 k 1 − ∑ i = 1 k 2 2 z i A=B*2^{k_1}-\\sum\\limits_{i=1}^{k_2} 2^{z_i} A=B∗2k1−i=1∑k22zi
其中 z i ∈ [ 0 , k 1 ] z_i\\in[0,k_1] zi∈[0,k1]
那么我们可以枚举 k 1 k_1 k1的值,可以得到 C = ∑ i = 1 k 2 2 z i = B ∗ 2 k 1 − A C=\\sum\\limits_{i=1}^{k_2} 2^{z_i}=B*2^{k_1}-A C=i=1∑k22zi=B∗2k1−A
显然 k 2 k_2 k2最小就是 C C C中的二进制位 1 1 1的个数
对这些 k 1 + k 2 k_1+k_2 k1+k2取个最小值就好了
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int maxn = 3e5+10;
int A,B;
int bit(int x,int k1)
{
int ans = 0, base = 1;
for(int i=0;i<=60;i++)
{
if( (x>>i)&1 ) ans += base;
if( i>=k1 ) base *= 2;
}
return ans;
}
signed main()
{
cin >> A >> B;
int base = 1, ans = 1e18;
for(int k1=0;k1<=30;k1++)
{
int C = B*base-A;
if( C>=0 )
ans = min( ans,bit(C,k1)+k1 );
base = base*2;
}
cout << ans;
}
//536780502 141579856
E.Rainbow Strings
签到,乘一下就好了
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1<<26;
const int mod = 11092019;
int n,in[27];
char a[maxn];
unordered_map<int,int>mp;
signed main()
{
for(int i=0;i<=25;i++) mp[1<<i] = i;
cin >> ( a+1 ); n = strlen( a+1 );
for(int i=1;i<=n;i++) in[a[i]-'a']++;
int ans = 1;
for(int i=0;i<=25;i++) ans = 1ll*ans*( in[i]+1 )%mod;
cout << ans;
}
C.Coloring Contention
题意
A l i c e Alice Alice把每条边染色为红色或蓝色,然后 B o b Bob Bob选择一条 1 1 1到 n n n的最小颜色改变数的路径
现在 A l i c e Alice Alice要最大化颜色的改变数,输出这个改变数
起始很简单,
#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5+10;
vector<int>vec[maxn];
int n,m,vis[maxn],dis[maxn];
void bfs()
{
queue<int>q; q.push( 1 ); vis[1] = 1;
while( !q.empty() )
{
int u = q.front(); q.pop();
for(auto v:vec[u] )
{
if( vis[v] ) continue;
q.push( v ); vis[v] = 1; dis[v] = dis[u]+1;
}
}
cout << dis[n]-1;
}
int main()
{
cin >> n >> m;
for(int i=1;i<=m;i++)
{
int l,r; cin >> l >> r;
vec[l].push_back( r ); vec[r].push_back( l );
}
bfs();
}
A.Radio Prize
设 u u u到 v v v的路径权值和为 x x x,这条路径的代价为 x ∗ ( t u + t v ) x*(t_u+t_v) x∗(tu+tv)
定义 f [ u ] f[u] f[u]表示 u u u子树内所有节点到 u u u的距离之和, g [ u ] g[u] g[u]表示子树内的点到自己产生的花费
s i z [ u ] siz[u] siz[u]表示子树 u u u内的节点个数, s u m t [ u ] sumt[u] sumt[u]表示 u u u子树内的点权和
这个信息树形 d p dp dp一遍就知道了,接下来考虑换根
定义节点 u u u往父亲延申的子树到节点 u u u的距离和为 F [ u ] F[u] F[u], G [ u ] G[u] G[u]则表示到自己产生的花费
f s i z [ u ] fsiz[u] fsiz[u]表示节点个数, f s u m t [ u ] fsumt[u] fsumt[u]表示点权和
显然点 u u u的答案就是 g [ u ] + G [ u ] + t [ u ] ∗ ( f [ u ] + F [ u ] ) g[u]+G[u]+t[u]*(f[u]+F[u]) g[u]+G[u]+t[u]∗(f[u]+F[u])
问题是怎么得到 G , F , f s i z , f s u m t G,F,fsiz,fsumt G,F,fsiz,fsumt数组才是关键,考虑递推关系
v v v是 u u u的儿子,现在需要递推 F [ v ] F[v] F[v]和 G [ v ] G[v] G[v]
f
s
i
z
v
=
f
s
i
z
u
+
(
s
i
z
u
−
1
−
s
i
z
v
以上是关于2019-2020 ACM-ICPC Pacific Northwest Regional Contest (Div. 1)的主要内容,如果未能解决你的问题,请参考以下文章 2019-2020 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) 2019-2020 ACM-ICPC Pacific Northwest Regional Contest (Div. 1) 2019-2020 ACM-ICPC Latin American Regional Programming Contest A- Algorithm Teaching 二分图 2019-2020 ACM-ICPC Latin American Regional Programming Contest I - Improve SPAM 树形dp? 2019-2020 ACM-ICPC Brazil Subregional Programming Contest Problem A Artwork (并查集)