Codeforces Round #847 (Div. 3) A ~ E

文章目录

  • A. Polycarp and the Day of Pi
      • 题意:
      • 答案:
  • B. Taisia and Dice
      • 题意:
      • 答案:
  • C. Premutation
      • 题意:
      • 答案:
  • D. Matryoshkas(补)
      • 题意:
      • 答案:
  • E.Vlad and a Pair of Numbers
      • 题意:
      • 答案:

第一次打Div3,感觉还是比div2简单很多,参与感比较强,不像div2坐牢hh。这场写了ABCE,D是赛后补的。

A. Polycarp and the Day of Pi

题意:

给一个最多30位的字符串问前多少位和圆周率相同

答案:

因为最多就30位所以直接和圆周率比较就可以了,背不了去百度。

/*
* @Author: gorsonpy
* @Date:   2023-01-27 19:49:28
* @Last Modified by:   gorsonpy
* @Last Modified time: 2023-01-27 22:39:31
*/
#include
using namespace std;
using PII = pair<int, int>;
using LL = long long;

#define x first
#define y second
#define YES cout << "YES" << endl
#define NO cout << "NO" << endl

const int N = 2e5 + 10;
int a[N], T, n, m;

int main()
{
	std::ios::sync_with_stdio(false);
	string t = "31415926535897932384626433832795028841971";
	cin >> T;
	while(T--)
	{
		string s;
		cin >> s;

		int ans = 0;
		for(int i = 0; i < s.size(); ++i)
		{
			if(s[i] == t[i]) ++ans;
			else break;
		}

		cout << ans << endl;
	}
	return 0;
}


B. Taisia and Dice

题意:

给出一个只包含0到6的序列a,然后被偷走了一个最大值,原先序列和是s,x现在变成了r,求原序列的一种可能构造。

答案:

被偷走的最大值是可以直接计算的,把他放在第一个位置,也即是s-r,因为n只有50,所以后面的数字以直接逐层逐个放上去,先都只放一个再都只放两个直到和达到r为止即可。时间复杂度O( r r r)。

/*
* @Author: gorsonpy
* @Date:   2023-01-27 19:49:28
* @Last Modified by:   gorsonpy
* @Last Modified time: 2023-01-27 22:45:47
*/
#include
using namespace std;
using PII = pair<int, int>;
using LL = long long;

#define x first
#define y second
#define YES cout << "YES" << endl
#define NO cout << "NO" << endl

const int N = 2e5 + 10;
int T, n, m, s, r;

int main()
{
	std::ios::sync_with_stdio(false);
	cin >> T;
	while(T--)
	{
		cin >> n >> s >> r;
		vector<int> a(n);
		a[0] = s - r;

		int cnt = 0;
		while(cnt < r)
		{
			for(int i = 1; i < n; ++i)
			{
				a[i] ++;
				++cnt;
				if(cnt == r) break;
			}
		}

		for(int i = 0; i < n; ++i) cout << a[i] << " "; 
		cout << endl;
	}
	return 0;
}


C. Premutation

题意:

给出n个序列,分别代表原排列跳过一个数字后显示的结果,还原原排列a(保持原顺序)

答案:

对于第一个元素 a 1 a_1 a1来说,给出的n个序列只有一个是跳过他的,其他都是正常的,所以 a 1 a_1 a1可以扫描给出的序列得到(出现非一次的就是真正的第一个元素),同时我们知道跳过 a 1 a_1 a1的是哪一个序列,把这个序列接在判断出的 a 1 a_1 a1后就是原排列了。时间复杂度O( n 2 ) n^2) n2)

/*
* @Author: gorsonpy
* @Date:   2023-01-27 19:49:28
* @Last Modified by:   gorsonpy
* @Last Modified time: 2023-01-27 22:57:59
*/
#include
using namespace std;
using PII = pair<int, int>;
using LL = long long;

#define x first
#define y second
#define YES cout << "YES" << endl
#define NO cout << "NO" << endl

const int N = 110;
int cnt[N], a[N][N], T, n, m;

int main()
{
	std::ios::sync_with_stdio(false);
	cin >> T;
	while(T--)
	{
		memset(cnt, 0, sizeof cnt);
		cin >> n;
		for(int i = 1; i <= n; ++i)
		{
			for(int j = 1; j < n; ++j)
				cin >> a[i][j];
			cnt[a[i][1]] ++;
		}
		int first;

		for(int i = 1; i <= n; ++i)
			if(cnt[i] > 1) first = i;

		cout << first << " ";
		for(int i = 1; i <= n; ++i)
			if(a[i][1] != first)
			{
				for(int j = 1; j < n; ++j)
					cout << a[i][j] << " ";
			}
		cout << endl;
	}
	return 0;
}


D. Matryoshkas(补)

题意:

类似于打牌,问你最多用多少个顺子就能打完所有牌,当然顺子带的个数不像打牌那样有限制。

答案:

比赛的时候到这里直接卡住,一开始想的是去模拟一下,但是感觉情况有点复杂,因为上一个比自己点数小1的牌可能有可能没有,而且数量也不一定,写了几次都模拟不出来,然后就跳过去写E了,挺可惜的。官方的题解给出的做法很巧妙,首先因为给出的牌可能有的点数是没有出现的,设给出的牌堆为a,我们维护一个集合S, 那么对于所有的 a i a_i ai,都把 a i a_i ai a i + 1 a_{i}+1 ai+1放入集合S中(不管是否真的出现过那个点数,然后维护一个cnt数组记录每个点数实际真正出现的次数。这样做的好处是我们不管给出的牌如何我们都可以完整遍历所有点数.)同时维护一个last变量用来表示上一个点数的实际个数。每迭代一个点数x都让ans += max(0, cnt[x] - last).
为什么这样做呢,对于打顺子,我们只在一个顺子开始的时候添加答案。比如说2 3 4 5这个顺子,我们统一只在看2的时候增加答案,5这个结尾的时候就不增加了。同时顺子可以翻倍,比如2 2 3 3 4 4 5 5,我们显然可以拆出2个顺子,答案就是+2. 然后考虑两个特殊一点情况:
如果中间有数字多了呢,比如2 2 3 3 4 4 4 5 5,多了一个4,那么当我们看到4的时候要开辟一个新的顺子,也就是cnt[4] - last. 然后情况又回归和上面相同。
如果数字少了,如 2 2 3 3 4 5 5,这个时候看到4的时候不需要对答案做出任何改动(ans += 0),这是因为看到5的时候会加上1,新开辟一个顺子,答案仍正确。

这题还有一个很有意思的地方就是unordered_map哈希表应该是赛后被hack了,如果用hash表这题会T,要用map。时间复杂度O( n l o g n ) nlogn) nlogn)

/*
* @Author: gorsonpy
* @Date: 2023-01-29 20:07
* @Last Modified by: gorsonpy
* @Last Modified time: 2023-01-29 20:07
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
using PII = pair<int, int>;
using LL = long long;

#define x first
#define y second

const int N = 2e5 + 10;
int a[N], T, n, m;

int main()
{
    std::ios::sync_with_stdio(false);
    cin >> T;
    while(T--)
    {
        set<int> S;
        cin >> n;
        map<int, int> cnt;
        for (int i = 1; i <= n; ++i)
        {
            int x;
            cin >> x;
            cnt[x]++;
            S.insert(x), S.insert(x + 1);
        }

        int last = 0, ans = 0;
        for(auto x : S)
        {
            int c = cnt[x];
            ans += max(0, c - last);
            last = c;
        }

        cout << ans << endl;
    }
    return 0;
}

E.Vlad and a Pair of Numbers

题意:

给出a xor b的值(x),求能使得(a + b) / 2 = x的一组解。

答案:

稍作变形有 ( a + b ) = 2 x (a + b) = 2x (a+b)=2x, 且要满足 a x o r b = x a xor b = x axorb=x, 设 a = ( a 29 a 28 . . . a 1 a 0 ) 2 , b = ( b 29 b 28 . . . b 1 b 0 ) 2 , x = ( x 29 x 28 . . . x 1 x 0 ) 2 a = (a_{29}a_{28}...a_{1}a_{0})_2, b = (b_{29}b_{28}...b_{1}b_{0})_2, x = (x_{29}x_{28}...x_{1}x_{0})_2 a=(a29a28...a1a0)2,b=(b29b28...b1b0)2,x=(x29x28...x1x0)2,若 x i = 1 x_i = 1 xi=1, 那么a,b只能有一个1,因为大小无所谓,不妨就加到a上;若 x i = 0 x_i=0 xi=0,那么 a i = b i a_i = b_i ai=bi,要么都是1要么都是0.又因为每一个数字都能被二进制表示,所以一开始让a = x(也就是让a继承x的所有1),逐位迭代即可。若 x i = 0 x_i=0 xi=0,那么只要此时 a + b < 2 x a+b<2x a+b<2x就把a,b这一位都加上1,否则就不动,最后检查一下是否满足条件即可。

/*
* @Author: gorsonpy
* @Date:   2023-01-27 19:49:28
* @Last Modified by:   gorsonpy
* @Last Modified time: 2023-01-27 23:41:00
*/
#include
using namespace std;
using PII = pair<int, int>;
using LL = long long;

#define x first
#define y second
#define YES cout << "YES" << endl
#define NO cout << "NO" << endl

const int N = 2e5 + 10;
int a[N], T, n;

int main()
{
	std::ios::sync_with_stdio(false);
	cin >> T;

	while(T--)
	{
		int x;
		cin >> x;

		vector<int> pos(30);
		for(int i = 29; i >= 0; --i)
			pos[i] = (x >> i & 1);

		int a = x, b = 0;
		x <<= 1;

		int m = a;
		for(int i = 29; i >= 0; --i)
		{
			if(!pos[i] && m + 2 * (1 << i) <= x) 
				a += (1 << i), b += (1 << i), m += 2 * (1 << i);
		}

		if(m == x) cout << a << " " << b << endl;
		else cout << -1 << endl;
	}
	return 0;
}


你可能感兴趣的:(c++,算法,数据结构)