传智杯省赛(复赛)个人题解(231217场)

传智杯省赛(复赛)个人题解(231217场)

A小红劈字符串

题目:

小红拿到了一个字符串,她准备把这个字符串劈成两部分,使得第一部分的长度恰好是第二部分的两倍。你能帮她吗?

输入描述:

一个仅由小写字母构成的字符串,长度不超过 1 0 5 10^5 105

输出描述:

如果无解,亲输出 − 1 -1 1

否则输出两个字符串,用空格隔开,代表劈完了的字符串。

示例1
输入
abc
输出
ab c
示例2
输入
ad
输出
-1

解题思路

先获取字符的长度 n n n,判断是否为 3 3 3的倍数,不是的话输出 − 1 -1 1,因为非3的倍数完整切割成符合要求的两份。是 3 3 3的倍数则先将 n n n 3 3 3获得 x x x,将字符串 s s s 0 − 2 ∗ x 0-2*x 02x切开,再从 2 ∗ x − n 2*x-n 2xn切开,就得到了答案

题解

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <unordered_map>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <list>

#define fi first
#define se second
#define endl '\n'

using namespace std;

typedef long long ll;

typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<string, string> pss;
typedef pair<string, int> psi;

typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<string> vs;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<pss> vpss;
typedef vector<vi> vvi;

typedef queue <int> qi;
typedef queue <ll> ql;
typedef queue <pii> qpii;
typedef queue <psi> qpsi;

typedef priority_queue<int> pqi;
typedef priority_queue<string> pqs;
typedef priority_queue<pii> pqpii;
typedef priority_queue<psi> pqpsi;

typedef unordered_map<int, int> umapii;
typedef unordered_map<string, int> umapsi;

const int N = 1e5 + 5;

void solve()
{
	string s;
	cin >> s;
	int n = s.length();
	if (n % 3 != 0)
	{
		cout << -1 << endl;
		return;
	}
	int x = n / 3;
	string a = s.substr(0, x * 2);
	string b = s.substr(x * 2, n);
	cout << a << " " << b << endl;
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int t = 1;
	//cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}

B小红的数字分裂

题目:

小红有一个数组,她每次可以选择数组的一个元素 x x x,将这个元素分成两个元素 a a a b b b,使得 a + b = x a+b=x a+b=x

请问小红最少需要操作多少次才可以使得数组的所有元素都相等。

输入描述:

第一行输入一个整数 n ( 1 ≤ n ≤ 1 0 5 ) n(1≤n≤10^5) n(1n105)表示数组长度。

第二行输入 n n n个整数表示数组 a ( 1 ≤ a i ≤ 1 0 9 ) a(1≤a_i≤10^9) a(1ai109)

输出描述:

输出一个整数表示答案

示例1
输入
2
2 4
输出
1
说明
操作1次,将4分成2和2,数组变成[2,2,2]

解题思路

先计算出数组 a a a中所有元素的最大公因数 m x G c d mxGcd mxGcd,然后统计数组中所有元素切成 m x G c d mxGcd mxGcd需要的次数。

题解

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <unordered_map>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <list>

#define fi first
#define se second
#define endl '\n'

using namespace std;

typedef long long ll;

typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<string, string> pss;
typedef pair<string, int> psi;

typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<string> vs;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<pss> vpss;
typedef vector<vi> vvi;

typedef queue <int> qi;
typedef queue <ll> ql;
typedef queue <pii> qpii;
typedef queue <psi> qpsi;

typedef priority_queue<int> pqi;
typedef priority_queue<string> pqs;
typedef priority_queue<pii> pqpii;
typedef priority_queue<psi> pqpsi;

typedef unordered_map<int, int> umapii;
typedef unordered_map<string, int> umapsi;

const int N = 1e5 + 5;

int gcd(int a, int b)
{
	return b == 0 ? a : gcd(b, a % b);
}

void solve()
{
	ll n; cin >> n;
	vl a(n);
	for (int i = 0; i < n; i++)
	{
		cin >> a[i];
	}
	ll mxGcd = a[0];
	for (int i = 0; i < n; i++)
	{
		mxGcd=gcd(mxGcd, a[i]);
	}
	ll cnt = 0;
	for (int i = 0; i < n; i++)
	{
		cnt += (a[i] / mxGcd) - 1;
	}
	cout << cnt << endl;
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int t = 1;
	//cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}

C小红的字符串同构

题目:

有两个等长字符串 a a a b b b,如果对于所有的 a [ i ] − b [ i ] ( 1 ≤ i ≤ ∣ b ∣ ) a[i]-b[i](1≤i≤|b|) a[i]b[i](1ib)为定值,则称它们为同构的。例如字符串" a b c d abcd abcd"和字符串“ e f g h efgh efgh"同构。

小红现在有一个字符串 a a a,她想获得一个满足以下两个条件的等长的字符串 b b b。请问 b b b一共有多少种?

  • a a a b b b的每一位都不同,即 a [ i ] ! = b [ i ] ( 1 ≤ i ≤ ∣ b ∣ ) a[i]!=b[i](1≤i≤|b|) a[i]!=b[i](1ib)
  • a a a b b b不同构
输入描述:

第一行输入一个字符串 a ( 1 ≤ ∣ a ∣ ≤ 1 0 5 ) a(1≤|a|≤10^5) a(1a105)

输出描述:

输出一个整数表示答案。答案可能过大,需要模 1 0 9 + 7 10^9+7 109+7

示例1
输入
a
输出
0
说明
所有长度为1的字符串于a都同构
示例2
输入
ab
输出
601

解题思路

观察同构规则,不难发现如果字符串 a a a于字符串 b b b同构,则 a a a b b b的每一位都不同,即条件2包含了条件1,所以我们只需要先计算出每一位都不同的字符串的数量,再减去同构字符串的数量就是答案。

对于字符串 a a a,计算每一位都不同的字符串的数量,即计算每一位除了它本身在这一位的字母的数量相乘,例如对于“ a b ab ab”来说,第一位除了 a a a 25 25 25种字母,第二位除了 b b b 25 25 25种字母,所以每一位都不同的字符串的数量为 25 × 25 = 625 25×25=625 25×25=625种。( 2 5 n ( 1 ≤ n ≤ 1 0 5 ) 25^n(1≤n≤10^5) 25n(1n105)比较大,要使用快速幂求)

计算字符串 a a a的重构字符串数量,先找出 a a a中最大的字符,再找出 a a a中最小的字符,字符域长度减去 a a a的值域长度就是重构字符串数量。例如对于“ a b ab ab”来说,最大的字符是 b b b,最小的字符是 a a a。值域长度就是 b − a + 1 = 2 b-a+1=2 ba+1=2,字符域长度 26 − 2 = 24 26-2=24 262=24就是重构字符串数量。而对于“ a z az az”来说,重构字符串数量是 0 0 0

题解

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <unordered_map>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <list>

#define fi first
#define se second
#define endl '\n'

using namespace std;

typedef long long ll;

typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<string, string> pss;
typedef pair<string, int> psi;

typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<string> vs;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<pss> vpss;
typedef vector<vi> vvi;

typedef queue <int> qi;
typedef queue <ll> ql;
typedef queue <pii> qpii;
typedef queue <psi> qpsi;

typedef priority_queue<int> pqi;
typedef priority_queue<string> pqs;
typedef priority_queue<pii> pqpii;
typedef priority_queue<psi> pqpsi;

typedef unordered_map<int, int> umapii;
typedef unordered_map<string, int> umapsi;

const int N = 1e5 + 5;
const int MOD = 1e9 + 7;

ll quickPow(ll x, ll n)
{
	ll res = 1;
	while (n)
	{
		if (n & 1)
			res = res * x % MOD;
		x = x * x % MOD;
		n >>= 1;
	}
	return res;
}

ll cal(ll n)
{
	ll res = 1;
	while (n)
	{
		res = res * n % MOD;
		n--;
	}
	return res;
}

void solve()
{
	string s;
	cin >> s;
	int n = s.length();
	ll ans = quickPow(25, n);
	char mxChar = *max_element(s.begin(), s.end());
	char mnChar = *min_element(s.begin(), s.end());
	ll len = ll(mxChar - mnChar + 1);
	ans = ans - (26 - len);
	cout << ans << endl;
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int t = 1;
	//cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}

E

原题链接

改编自Problem - D - Codeforces

题目:

一开始,你有一个空的线段集合。你需要处理q 个两种类型的操作:

  • + l r — 将线段 ( l , r ) (l, r) (l,r) 添加到集合中,
  • - l r — 从集合中删除恰好一个线段 ( l , r ) (l, r) (l,r)。保证该线段存在于集合中。

在每次操作后,你需要判断集合中是否存在相交的线段。(一对线段$ (l, r)$ 和$ (a, b)$ 不相交,如果不存在一个点 x 使得 l ≤ x ≤ r l ≤ x ≤ r lxr 并且 a ≤ x ≤ b a ≤ x ≤ b axb。)

输入描述:

每个测试用例的第一行包含一个整数 q ( 1 ≤ q ≤ 1 0 5 ) q (1 ≤ q ≤ 10^5) q(1q105) — 操作的次数。

接下来的 q 行描述了两种操作类型。如果是添加操作,则格式为 + l r。如果是删除操作,则格式为 - l r ( 1 ≤ l ≤ r ≤ 1 0 9 ) (1 ≤ l ≤ r ≤ 10^9) (1lr109)

输出描述:

在每次操作后,如果集合中存在相交的线段,则打印 “Yes”,否则打印 “No”。

示例1:
输入
4
+ 1 2
+ 4 5
+ 3 4
- 4 5
输出
No
No
Yes
No

解题思路

先插入一个 1 − 1 0 9 1-10^9 1109的区间,全部赋值为0。+ l r插入区间就相当于做区间加法,区间 [ l , r ] + 1 [l,r]+1 [l,r]+1- l r删去区间去相当于区间减法 [ l , r ] − 1 [l,r]-1 [l,r]1。每操作完一次之后遍历一遍区间,检查是否有点 ≥ 2 ≥2 2。我使用的是珂朵莉树来维护区间(珂朵莉树天下第一),具体原理可以看我的博客基于STL库set容器实现的珂朵莉树

题解:

#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <vector>
#include <algorithm>
#include <set>
#include <unordered_map>
#include <string>
#include <queue>
#include <stack>
#include <map>
#include <list>

#define fi first
#define se second
#define endl '\n'

using namespace std;

typedef long long ll;

typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<string, string> pss;
typedef pair<string, int> psi;

typedef vector<bool> vb;
typedef vector<int> vi;
typedef vector<ll> vl;
typedef vector<string> vs;
typedef vector<pii> vpii;
typedef vector<pll> vpll;
typedef vector<pss> vpss;
typedef vector<vi> vvi;

typedef queue <int> qi;
typedef queue <ll> ql;
typedef queue <pii> qpii;
typedef queue <psi> qpsi;

typedef priority_queue<int> pqi;
typedef priority_queue<string> pqs;
typedef priority_queue<pii> pqpii;
typedef priority_queue<psi> pqpsi;

typedef unordered_map<int, int> umapii;
typedef unordered_map<string, int> umapsi;

const int N = 5e5 + 5;
int n, q, l, r;
char opt;

struct node
{
	int _left, _right;
	mutable int _val;
	node(int L = 0, int R = -1, int V = 0) :_left(L), _right(R), _val(V) {}
	bool operator < (const node& x) const
	{
		return _left < x._left;
	}
};

set<node> s;

auto split(int p)
{
	auto iter = s.lower_bound(node(p));
	if (iter != s.end() && iter->_left == p)
		return iter;
	iter--;
	int l = iter->_left;
	int r = iter->_right;
	int v = iter->_val;
	s.erase(iter);
	s.insert(node(l, p - 1, v));
	return s.insert(node(p, r, v)).first;
}

void add(int l, int r, char opt)
{
	auto itR = split(r + 1);
	auto itL = split(l);
	int v = opt == '+' ? 1 : -1;
	for (auto iter = itL; iter != itR; iter++)
	{
		iter->_val += v;
	}
}

bool ask(int l, int r)
{
	auto itR = split(r + 1);
	auto itL = split(l);

	for (auto iter = itL; iter != itR; iter++)
	{
		if (iter->_val > 1)
			return true;
	}
	return false;
}

void solve()
{
	cin >> q;
	const int L = 1;
	const int R = 1e9 + 5;
	s.insert(node(L, R, 0));
	while (q--)
	{
		cin >>opt>> l >> r;
		add(l, r, opt);
		if (ask(L, R))
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
}

int main()
{
	ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
	int t = 1;
	//cin >> t;
	while (t--)
	{
		solve();
	}
	return 0;
}
  • 48
    点赞
  • 66
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值