Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!

Posted lordxx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!相关的知识,希望对你有一定的参考价值。

解决:ABCDE 补题:F

A。
使a2,4,*8或者/2,/4,/8能否得到b。
令a为更小的值,a/2*2的效果一样,又a是小值,故只用考虑a*({2^k})能否得到b即可。然后贪心的选。(3=2+1,2=1+1)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<‘0‘ || ch>‘9‘) { if (ch == ‘-‘)f = -1; ch = getchar(); }
	while (ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int t;
ll a, b;
int main()
{
	t = read();
	while (t--)
	{
		a = read(), b = read();
		if (a > b)swap(a, b);
		if (a == b) {
			printf("0
");
			continue;
		}
		if (b%a !=0||b&1)
		{
			printf("-1
");
		}
		else {
			ll temp = b / a;
			ll sum = 0;
			if (temp & 1)
			{
				printf("-1
");
				continue;
			}
			bool flag = 0;
			dwd(i, 60, 0)
			{
				if (temp&(1ll << i))
				{
					if (sum == 0)
						sum = i;
					else flag = 1;
				}
			}
			if (flag)
			{
				printf("-1
");
			}
			else {
				int cnt = 0;
				while (sum)
				{
					if (sum >= 3)sum -= 3;
					else if (sum >= 2)sum -= 2;
					else if (sum >= 1)sum--;
					cnt++;
				}
				printf("%d
", cnt);
			}
		}
	}
	return 0;
}

B.
有a^b=c -> a^c=b,b^c=a。故,a[i]^k=a[j],反过来,a[j]^k=a[i],k=a[i]^a[j]所以长度一定为偶数。考虑(n^2)遍历。得到1024以内的所有两两异或值,枚举这些值,当作k使用,判断可行性。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<‘0‘ || ch>‘9‘) { if (ch == ‘-‘)f = -1; ch = getchar(); }
	while (ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
int t;
int n;
const int N = 2000;
int a[N];
int main()
{
	t = read();
	while (t--)
	{
		n = read();
		upd(i, 1, n)a[i] = read();
		if (n & 1)
		{
			printf("-1
");
		}
		else {
			vector<int>vec;
			sort(a + 1, a + n + 1);
			upd(i, 1, n) {
				upd(j, i+1, n)
				{
					int temp = a[i] ^ a[j];
					vec.push_back(temp);
			} }
			sort(vec.begin(), vec.end());
			vec.erase(unique(vec.begin(), vec.end()), vec.end());
			bool last = 0;
			for (auto k : vec)
			{
				bool flag = 0;
				vector<int>temp;
				upd(i, 1, n)
				{
					temp.push_back(a[i] ^ k);
				}
				sort(temp.begin(), temp.end());
				temp.erase(unique(temp.begin(), temp.end()), temp.end());
				if (temp.size() != n) {
					flag = 1;
				}
				else {
					upd(i, 1, n)
					{
						if (temp[i - 1] != a[i])
							flag = 1;
					}
				}
				if (!flag)
				{
					printf("%d
", k);
					last = 1;
					break;
				}
			}
			if (!last) {
				printf("-1
");
			}
		}
	}
	return 0;
}

C
简单dp预处理。令dp[i]表示,二进制第i为即000..1000..000时,所拥有的不同数量。
(dp[i])=((sum_{j=1}^{i}{dp[j]})+i+1)(例如1000,与0111恰好多了3+1个即i+1)

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<‘0‘ || ch>‘9‘) { if (ch == ‘-‘)f = -1; ch = getchar(); }
	while (ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
ll dp[100];
void init()
{
	dp[0] = 1;
	dp[1] = 3;
	ll sum = 4;
	upd(i, 2, 61)
	{
		dp[i] = sum + i + 1;
		sum += dp[i];
	}
}
ll t, n;
int main()
{
	init();
	t = read();
	while (t--) {
		n = read();
		ll ans = 0;
		dwd(i, 60, 0) {
			if (n&(1ll << i))
			{
				ans += dp[i];
			}
		}
		printf("%lld
", ans);
	}
	return 0;
}

D
模拟即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<‘0‘ || ch>‘9‘) { if (ch == ‘-‘)f = -1; ch = getchar(); }
	while (ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 5e5 + 10;
int n, m;
vector<int>vec[N];
int a[N];
vector<int>num[N];
int ans[N];
int last[N];
int main() {
	n = read();
	m = read();
	int u, v;
	upd(i, 1, m) {
		u = read(), v = read();
		vec[u].push_back(v);
		vec[v].push_back(u);
	}
	upd(i, 1, n)a[i] = read();
	upd(i, 1, n)
	{
		num[a[i]].push_back(i);
	}
	int cnt = 0;
	bool flag = 0;
	upd(i, 1, n)
	{
		set<int>s;
		for (auto k : vec[i])
		{
			s.insert(a[k]);
		}
		int mex = 1;
		for (auto k : s) {
			if (k != mex)
			{
				break;
			}
			mex++;
		}
		if (mex != a[i])flag = 1;
		if (flag)break;
	}
	upd(i, 1, N-5)
	{
		if (num[i].size())
		{
			for (auto k : num[i])
			{
				ans[k] = ++cnt;
			}
		}
	}
	if (flag) {
		printf("-1
");
	}
	else {
		upd(i, 1, n)last[ans[i]] = i;
		upd(i, 1, n)printf("%d ", last[i]);
	}
	return 0;
}

E
首先给出结论,当我们考虑k进制时。如果从高位考虑到低位。
假设k进制的位数a[1]>=a[2]>=a[3]>=a[4]......
就有(k^{a[1]})>=(k^{a[2]}+k^{a[3]}+...+k^{a[j]})倘若当(k^{a[2]}+k^{a[3]}+...+k^{a[j]}+k^{a[j+1]})>(k^{a[1]}),此时必有(k^{a[2]}+k^{a[3]}+...+k^{a[j]})==(k^{a[1]})
拿二进制举例。枚举最高位假设:100000,最高位=5。接着往后枚举,432
有sum=(2^4+2^3+2^2)二进制表示为011100,倘若再来一个2(100),那么sum+=(2^2)sum二进制表示为100000。可以考虑为因从高位枚举到低位,我们在做树状数组时,有p+=lowbit(p)这里p一定小于最高位2次方的。所以我们这道题目就可以考虑,先往A组扔一个最高位,然后B组去凑这个最高位,当凑齐时,剪掉。然后重复这个操作。
注意的是,这道题目最开始考虑使用1e9+9这个模数。但这道题目卡掉了,猜测应该要使用不常见的模数。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<‘0‘ || ch>‘9‘) { if (ch == ‘-‘)f = -1; ch = getchar(); }
	while (ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 1e6 + 10;
int t;
ll n, p;
int ki[N];
int val[N];
const int mod = 1e9 + 7;
const int modd = 12255871;
ll quick_pow(ll a, ll b,int m)
{
	ll res = 1;
	while (b)
	{
		if (b & 1)res = (res*a) % m;
		b >>= 1;
		a = a * a%m;
	}
	return res;
}
int main()
{
	t = read();
	while (t--)
	{
		n = read(), p = read();
		upd(i, 1, n)ki[i] = read();
		sort(ki + 1, ki + n + 1);
		ll ans1 = 0, ans2 = 0;
		dwd(i, n, 1)
		{
			if (!ans1 && !ans2)
			{
				ans1 += quick_pow(p, ki[i], mod);
				ans2 += quick_pow(p, ki[i], modd);
				ans1 %= mod;
				ans2 %= modd;
			}
			else {
				ans1 = (ans1 + mod - quick_pow(p, ki[i], mod)) % mod;
				ans2 = (ans2 + modd - quick_pow(p, ki[i], modd)) % modd;
			}
		}
		printf("%lld
", ans1%mod);
	}
	return 0;
}

F
网上看到的一个很有意思的思路。
首先,我们考虑,k的计算。假设x^y=a,那么就有他的权值为(2^k)=lowbit(a)。其中k是权值。故,我们可以考虑,如果k是答案,那么x的lowbit一定等于y的lowbit(且最高位大于等于k),此时才会出现权值至少为k。我们考虑枚举k(因为k很小)。可以发现,当答案为k时,表示lowbit相等的至少最高位是k,故可以x^(1<<k-1)==y^(1<<k-1)来判断条件。
接着,发现因为两个相邻的必须相连,所以我们使用虚点,这个虚点同时连接i<<1,i<<1|1(即相邻的两个点)。但是这样依然没有解决问题。因为这样图连出来,是无序的。我们考虑简化该图。将可以连边的点,所称一个点。即若x和y满足上述条件,缩成一个点。这样构造出来的图,我们可以看成是二分图,一边是x^(1<<k-1)出来的点,一边是虚点。最后保证该项链能做成一个环,且该环中,保证所有点在内,我们只需要跑一个欧拉路即可。

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<cstdlib>
#include<climits>
#include<stack>
#include<vector>
#include<queue>
#include<set>
#include<bitset>
#include<map>
//#include<regex>
#include<cstdio>
#include <iomanip>
#pragma GCC optimize(2)
#define up(i,a,b)  for(int i=a;i<b;i++)
#define dw(i,a,b)  for(int i=a;i>b;i--)
#define upd(i,a,b) for(int i=a;i<=b;i++)
#define dwd(i,a,b) for(int i=a;i>=b;i--)
//#define local
typedef long long ll;
typedef unsigned long long ull;
const double esp = 1e-6;
const double pi = acos(-1.0);
const int INF = 0x3f3f3f3f;
const int inf = 1e9;
using namespace std;
ll read()
{
	char ch = getchar(); ll x = 0, f = 1;
	while (ch<‘0‘ || ch>‘9‘) { if (ch == ‘-‘)f = -1; ch = getchar(); }
	while (ch >= ‘0‘ && ch <= ‘9‘) { x = x * 10 + ch - ‘0‘; ch = getchar(); }
	return x * f;
}
typedef pair<int, int> pir;
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lrt root<<1
#define rrt root<<1|1
const int N = 2e6 + 10;
int n;
pir col[N];
vector<pir>vec[N];
int vis[N];
vector<int>ans;
void dfs(int u, int id)
{
	while (vec[u].size())
	{
		pir top = vec[u].back(); vec[u].pop_back();
		if (!vis[top.second])
		{
			vis[top.second] = 1;
			dfs(top.first, top.second);
		}
	}
	if (id != -1)ans.push_back(id);
}
bool check(int mask)
{
	ans.clear();
	int t = mask - 1;
	upd(i, 0, n + t)
		vec[i].clear();
	upd(i, 1, n)
	{
		vis[(i - 1) << 1] = 0;
		vis[(i - 1) << 1 | 1] = 0;
		vec[col[i].first&t].push_back(make_pair(t + i, (i - 1) << 1));
		vec[t + i].push_back(make_pair(col[i].first&t, (i - 1) << 1));
		vec[col[i].second&t].push_back(make_pair(t + i, (i - 1) << 1 | 1));
		vec[t + i].push_back(make_pair(col[i].second&t, (i - 1) << 1 | 1));
	}
	upd(i, 0, t+n)
	{
		if (vec[i].size() & 1)
		{
			return 0;
		}
	}
	upd(i, 0, t + n)
	{
		if (vec[i].size())
		{
			dfs(i, -1);
			break;
		}
	}
	if (ans.size() != 2 * n)
	{
		return 0;
	}
	return 1;
}
int main()
{
	n = read();
	upd(i, 1, n)
	{
		col[i].first = read(); col[i].second = read();
	}
	dwd(i, 20, 0)
	{
		if (check(1 << i))
		{
			printf("%d
", i);
			for (auto k : ans)
			{
				printf("%d ", k + 1);
			}
			break;
		}
	}
	return 0;
}















以上是关于Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!的主要内容,如果未能解决你的问题,请参考以下文章

Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!

Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!

Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!

Codeforces Round #647 (Div. 2) B. Johnny and His Hobbies(枚举)

Codeforces Round #647 (Div. 2) B. Johnny and His Hobbies(枚举)

Codeforces Round #647 (Div. 2) D. Johnny and Contribution(BFS)