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=B2k1i=1k22zi

其中 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=1k22zi=B2k1A

显然 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 (并查集)

ACM-ICPC 2017 Asia HongKong 解题报告