(Week 15)综合复习(C++,字符串,数学)

文章目录

    • T1 [Daimayuan]删删(C++,字符串)
        • 输入格式
        • 输出格式
        • 样例输入
        • 样例输出
        • 数据规模
        • 解题思路
    • T2 [Daimayuan]快快变大(C++,区间DP)
        • 输入格式
        • 输出格式
        • 样例输入
        • 样例输出
        • 数据规模
        • 解题思路
    • T3 [Daimayuan]饿饿 饭饭2(C++,数学)
        • 输入格式
        • 输出格式
        • 数据规模
        • 样例输入
        • 样例输出
        • 解题思路
    • T4 [Daimayuan]子串分值和(C++,字符串)
        • 输入格式
        • 输出格式
        • 样例输入
        • 样例输出
        • 数据规模
        • 解题思路
    • T5 [Daimayuan]蒟蒻(C++,STL)
        • 输入格式
        • 输出格式
        • 样例输入
        • 样例输出
        • 数据规模
        • 解题思路
    • T6 [Daimayuan]锦标赛(C++,模拟)
        • 输入格式
        • 输出格式
        • 样例输入1
        • 样例输出1
        • 样例输入输出2
        • 数据规模
        • 解题思路
    • T7 [Daimayuan]可重排列(C++,字符串)
        • 输入格式
        • 输出格式
        • 样例输入
        • 样例输出
        • 数据规模
        • 解题思路
    • T8 [Daimayuan]进制转换(C++)
        • 题面
        • 输入格式
        • 输出格式
        • 输入样例1
        • 输出样例1
        • 输入样例2
        • 输出样例2
        • 输入样例3
        • 输出样例3
        • 解题思路
    • T9 [Daimayuan]循环子串(C++,字符串)
        • 题目描述
        • 输入格式
        • 输出格式
        • 数据范围
        • 样例输入
        • 样例输出
        • 提示
        • 解题思路
    • T10 [Daimayuan]饿饿 饭饭之暑假大狂欢(C++,数学)
        • 输入格式
        • 输出格式
        • 数据范围
        • 样例输入
        • 样例输出
        • 解题思路

T1 [Daimayuan]删删(C++,字符串)

给定一个字符串,你可以删除多个(可以是 0 0 0) 相同 的字符,这样操作之后,你能否得到一个回文串?如果能,求最小化删除的个数。

输入格式

多组数据。

每一组数据包含两行,分别为字符串的长度 N N N,以及一个仅由小写字母组成的字符串 S S S

输出格式

对于每一组数据,输出一行。

如果不可能得到一个回文串,输出 − 1 −1 1。反之则输出最小操作次数。

样例输入

4
8
bilibili
3
qwq
9
daimayuan
7
xcpcxpc

样例输出

1
0
-1
2

解释:

在第一个例子中,删除开头的 b 得到 ilibili

第二个例子中,qwq 本身已回文,不需要操作。

第三个例子中,可以看到 daimayuan 不能靠仅删除一种字符得到一个回文串。

数据规模

1 ≤ N ≤ 1 0 5 1≤N≤10^5 1N105, 但保证 ∑ N ≤ 2 × 1 0 5 \sum{N}≤2×10^5 N2×105

解题思路

并没有巧妙的办法,就是简单的枚举 26 26 26种字母,找出其中删除的最少的即可

检测的思路如下:

从左右两端开始匹配

(1)if str[left] == str[right]left++, right--

(2)if str[left] != str[right]

如果左侧字符可以删除,那么删除左侧字符(left++

如果右侧字符可以删除,那么删除右侧字符(right--

如果左右都不可以删除,本轮删除失败,继续尝试下一个字符

#include <iostream>
#include <string>
using namespace std;
const int max_n = 2e5;
const string compose = "abcdefghijklmnopqrstuvwxyz";

string str;
int n1, n2;


int main() {
	cin >> n1;
	for (int i = 0; i < n1; i++) {
		cin >> n2 >> str;
		int ans = -1;
		for (char c: compose) {
			int l = 0, r = n2 - 1;
			int temp = 0;
			while (l <= r) {
				if (str[l] == str[r]) {
					l++; r--;
				}
				else {
					if (str[l] == c) {
						l++;
						temp++;
					}
					else if (str[r] == c) {
						r--;
						temp++;
					}
					else {
						temp = -1;
						break;
					}
				}
			}
			if (temp != -1)
				if (ans == -1) ans = temp;
				else ans = min(ans, temp);
		}
		cout << ans << endl;
	}
	return 0;
}

T2 [Daimayuan]快快变大(C++,区间DP)

给定一个长度为 n n n 的数组 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,,an,接下来进行 n − 1 n−1 n1 次操作。每次选择一个下标 x x x ,将 a x a_x ax a x + 1 a_{x+1} ax+1 合并成 a x ∗ a x + 1 m o d 1000003 a_x*a_{x+1}mod1000003 axax+1mod1000003 ,并且你会获得 ( a x − a x + 1 ) 2 (a_x−a_{x+1})^2 (axax+1)2 的分数。

所以每次操作后,数组的长度将会减 1 1 1,当最后只剩下一个元素时停止操作。输出最终能获得的最大分数。

输入格式

第一行一个数字 n n n

接下来一行 n n n 个整数 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,,an

输出格式

一个数,表示答案。

样例输入

3
1 2 3

样例输出

26

数据规模

所有数据保证 1 ≤ n ≤ 300 , 1 ≤ a i ≤ 1 0 6 1≤n≤300,1≤a_i≤10^6 1n300,1ai106

解题思路

是没见过的船新版本DP

首先简单说明一下每轮操作的含义

对于要合并的长度为 l e n len len的区间 [ l , r ] [l,r] [l,r],我们先分别合并左右两部分 [ l , k ] [l,k] [l,k] [ k + 1 , r ] [k+1,r] [k+1,r],那么容易知道:

dp[l][r] = max(dp[l][r], dp[l][k] + dp[k + 1][r] + (num[l][k] - num[k + 1][r]) ** 2)

也就是说合并区间 [ l , r ] [l,r] [l,r]所得到的分数等于分别合并左右区间得到的分数再加上最后一次合并得到的分数

D P DP DP的基本思想就是对于任意一个长度为 l e n len len的区间(第一重循环),我们尝试其所有可能的划分(第三重循环),找出其中的最大值

第二重循环?它负责遍历每一个长度为 l e n len len的区间

而我们从小到大遍历 l e n len len,保证了在动态规划过程中,所有长度小于 l e n len len的区间最优结构已经得到,所以 D P DP DP是可行的

AC代码如下

#include <iostream>
using namespace std;
const int mod_num = 1000003;
const int max_n = 300;

long long num[max_n + 1][max_n + 1], dp[max_n + 1][max_n + 1];
int n;


int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) cin >> num[i][i];
	for (int i = 1; i < n; i++) {
		for (int j = i + 1; j <= n; j++) {
			num[i][j] = num[j][j];
			num[i][j] = (num[i][j] * num[i][j - 1]) % mod_num;
		}
	}
	for (int len = 2; len <= n; len++) {
		for (int l = 1, r = len; r <= n; l++, r++) {
			for (int k = l; k < r; k++) {
				dp[l][r] = max(dp[l][r], dp[l][k] + dp[k + 1][r] + (num[l][k] - num[k + 1][r]) * (num[l][k] - num[k + 1][r]));
			}
		}
	}
	cout << dp[1][n] << endl;
	return 0;
}

T3 [Daimayuan]饿饿 饭饭2(C++,数学)

接着《饿饿 饭饭》 的故事,在两天后,食堂的工作人员回来了,整个食堂又回到了原来井井有条的状态。

两个月后,由于天气越来越热,大家的胃口越来越小了,作为食堂管理员的 C C CC CC非常担心孩子们的身体健康,所以他决定开展一个活动来调动孩子们吃饭的积极性,顺便考验一下孩子们的数学水平。活动内容如下:

先让每一个孩子都抽一个球,每一个球上有一个数字, 然后给这个孩子 n n n个数字,每一个孩子都有无数次操作机会,每一次都会选中一个数将它乘上 2 2 2,或者乘上 3 3 3,请问这个孩子可以通过上面的操作将这 n n n个数都变成相同的吗?

如果回答正确,这个回答正确的孩子就可以得到一份免费的午餐,但是这对于孩子们来说是在是太困难了,但是他们都想吃到免费的午餐,所以他们都想请你告诉他们正确的答案,让他们都迟到免费的午餐。

输入格式

1 1 1行给定一个数 T T T,表示有 T T T个小孩子请你告诉他正确的答案。

2 2 2 T + 1 T+1 T+1行,第 1 1 1个数是每个孩子抽到的数字 n n n,第 2 2 2 n + 1 n+1 n+1个数是对应的 n n n个数字。

输出格式

如果可以变成相同的,输出YES。如果不能变成相同的,输出NO

数据规模

1 ≤ T ≤ 100 , 1 ≤ n ≤ 2 × 1 0 5 , 1 ≤ a i ≤ 1 0 9 1≤T≤100,1≤n≤2×10^5,1≤a_i≤10^9 1T100,1n2×105,1ai109

数据保证 ∑ i = 1 T n ≤ 2 × 1 0 5 \sum^{T}_{i=1}{n}≤2×10^5 i=1Tn2×105

样例输入

2
4 75 150 75 50
3 100 150 250

样例输出

YES
NO

解题思路

将每个数字拆解成两部分的乘积: 2 、 3 2、3 23和其他数字

我们尝试把所有数字的第一部分除去,如果剩余部分相等,输出YES

反之,输出NO

AC代码如下

#include <iostream>
using namespace std;
const int max_t = 100;
const int max_n = 2e5;
const int max_a = 1e9;

int t, n;
int num_arr[max_n];


int main() {
	cin >> t;
	for (int i = 0; i < t; i++) {
		cin >> n;
		for (int j = 0; j < n; j++) {
			cin >> num_arr[j];
			while (num_arr[j] % 2 == 0) num_arr[j] /= 2;
			while (num_arr[j] % 3 == 0) num_arr[j] /= 3;
		}

		int j, same = num_arr[0];
		for (j = 1; j < n; j++) if (num_arr[j] != same) break;
		if (j != n) cout << "NO" << endl;
		else cout << "YES" << endl;
	}
	return 0;
}

T4 [Daimayuan]子串分值和(C++,字符串)

对于一个字符串 S S S ,我们定义 f ( S ) f(S) f(S) S S S 中出现的不同的字符个数。 例如 f ( a b a ) = 2 f(aba)=2 f(aba)=2 f ( a b c ) = 3 f(abc)=3 f(abc)=3, f ( a a a ) = 1 f(aaa)=1 f(aaa)=1

现在给定一个字符串 S S S (假设长度为 l e n len len),请你计算 ∑ i = 0 l e n − 1 ∑ j = i l e n − 1 f ( S [ i : j ] ) \sum_{i=0}^{len−1}\sum_{j=i}^{len−1}f(S[i:j]) i=0len1j=ilen1f(S[i:j])

输入格式

输入一行包含一个由小写字母组成的字符串 S S S

输出格式

输出一个整数表示答案。

样例输入

ababc

样例输出

28

数据规模

所有数据保证字符串长度 l e n ≤ 1000000 len≤1000000 len1000000,字符串下标从 0 0 0 l e n − 1 len−1 len1

解题思路

直接正面求解每一个字符串的分值显然会 T L E TLE TLE,那么尝试其他方法

我们的想法是单独处理每一个字符的分值,然后累加起来

直接去找该字符出现在多少字符串中并不容易,正难则反,我们尝试去寻找该字符没有出现在多少字符串中

举个例子ababc,其中a没有出现的字符串显然只有b,b,c,bc

所以想要找到所有没有出现a的字符串,我们只需要保存a出现过的每一个位置,然后根据间隔字符串长度计算即可

AC代码如下

#include <iostream>
#include <vector>
using namespace std;
const string alpha = "abcdefghijklmnopqrstuvwxyz";
const int max_len = 1e6;

vector<int>vocab[26];
long long ans = 0;


inline long long calc(long long num) {
	return num * (num + 1) / 2;
}


int main() {
	string str;
	cin >> str;
	int len = str.size();
	for (int i = 0; i < len; i++) {
		vocab[str[i] - 'a'].push_back(i);
	}
	for (char c : alpha) {
		long long sum = calc(len);
		if (!vocab[c - 'a'].empty()) {
			int l = 0;
			auto iter = vocab[c - 'a'].begin();
			while (iter != vocab[c - 'a'].end()) {
				sum -= calc(*iter - l);
				l = *iter + 1; iter++;
			}
			sum -= calc(len - l);
			ans += sum;
		}
	}
	cout << ans << endl;
	return 0;
}

后排提醒:要开long long,否则会炸

T5 [Daimayuan]蒟蒻(C++,STL)

便利蜂的货架上摆了一排蒟蒻果冻,搞得鶸尛鱻眼花缭乱…

对于每个果冻,都有一个价格 w w w 和口感 t t t。鶸尛鱻有一个购物篮子,在挑选蒟蒻果冻的时候,他有以下几种操作:

  • 操作 1 1 1:把一个价格为 w w w,口感为 t t t 的果冻放入篮子。
  • 操作 2 2 2:拿出篮子中 最为廉价 的果冻。
  • 操作 3 3 3:拿出篮子中 口感最差 的果冻。( t t t 越小,口感越差)

鶸尛鱻不喜欢重复,当操作 1 1 1价格或口感 与篮中已有果冻重复时,他会立刻将其放回货架。

经过 n n n 次操作后,鶸尛鱻确定了要购买的若干果冻,请你帮他求出篮子里果冻的总价格。

输入格式

1 1 1 行一个正整数 n n n,代表操作次数。

2 2 2 行至第 ( n + 1 n+1 n+1)( n + 1 n+1 n+1) 行,每行 一个或三个 整数,分别表示 o p op op w w w t t t

w w w t t t 当且仅当 o p = 1 op=1 op=1 时存在。

输出格式

输出一个整数,表示篮子里果冻的总价格。

样例输入

6
1 1 1
1 2 5
2
1 3 3
3
1 5 2

样例输出

7

数据规模

所有数据保证 1 ≤ n ≤ 1 0 5 1≤n≤10^5 1n105 1 ≤ w , t ≤ 1 0 6 1≤w,t≤10^6 1w,t106,且保证输入合法

解题思路

需要维护两个顺序,一个是价格的升序排序,一个是口感的升序排序

显然需要维护两个数组,关键在于使两个数组维持同步

利用maperase操作可以根据键值删除元素的性质,可以很容易实现这一点

AC代码如下

#include <iostream>
#include <map>
using namespace std;
const int max_n = 1e5;
const int max_w = 1e6;
const int max_t = 1e6;

map<int, int>m1, m2;
int w, t, n, op;
long long ans;


int main() {
	cin >> n;
	for (int i = 0; i < n; i++) {
		cin >> op;
		if (op == 1) {
			cin >> w >> t;
			if (m1.count(w) == 0 && m2.count(t) == 0) {
				m1[w] = t;
				m2[t] = w;
			}
		}
		else if (op == 2) {
			m2.erase(m1.begin()->second);
			m1.erase(m1.begin());
		}
		else {
			m1.erase(m2.begin()->second);
			m2.erase(m2.begin());
		}
	}

	for (auto it : m1) {
		ans += (long long)(it.first);
	}
	cout << ans << endl;
	return 0;
}

T6 [Daimayuan]锦标赛(C++,模拟)

n n n个玩家参加比赛,他们分别有能力值 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,,an

需要进行 n − 1 n−1 n1轮比赛,每一轮在剩下的玩家里任选两个玩家 i , j i,j i,j。如果 ∣ a i − a j ∣ > K |a_i−a_j|>K aiaj>K,那么其中能力值高的玩家会获胜,能力值低的玩家会被淘汰。如果 ∣ a i − a j ∣ ≤ K |ai−aj|≤K aiajK,那么两个玩家都有可能获胜,另一个玩家被淘汰。

n − 1 n−1 n1轮比赛之后,只剩下一个玩家。问有多少个玩家可能是最后获胜的玩家。

输入格式

第一行,两个整数 n , K n,K n,K,表示玩家的总人数,和获胜条件中的参数。

接下来一行 n n n个整数 a 1 , a 2 , … , a n a_1,a_2,…,a_n a1,a2,,an,表示玩家的能力值。

输出格式

一个整数,表示最后可能获胜的玩家个数。

样例输入1

5 3
1 5 9 6 3

样例输出1

5

样例输入输出2

见下发文件。

数据规模

10 10 10组数据。

测试点 1 1 1满足 n ≤ 5 n≤5 n5

测试点 2 2 2满足 n ≤ 10 n≤10 n10

测试点 3 , 4 , 5 3,4,5 3,4,5满足 n ≤ 1000 n≤1000 n1000

对于 100 100 100%的数据,满足 n ≤ 1 0 5 n≤10^5 n105, 1 ≤ a i , K ≤ 1 0 9 1≤a_i,K≤10^9 1ai,K109

解题思路

能力值越高的越容易获胜,这是显然的

如果我们要计算最多有多少人可能获胜,自然要求出能获胜的最低能力值是多少

题目中给出了一个能够以弱胜强的最大能力差值 K K K,能力差值大于 K K K的时候弱的一方不可能获胜

所以我们让能力值大的先开始比赛,每次比赛都让能力值小的一方获胜(前提是能获胜)

最后当能力值小的一方不可能获胜的时候,我们就得到了最多有多少人可能获胜

AC代码如下

#include <iostream>
#include <algorithm>
using namespace std;
const int max_n = 1e5;
const int max_a = 1e9;
const int max_k = 1e9;

int n;
long long k, gamer[max_n + 1];


int main() {
	cin >> n >> k;
	for (int i = 1; i <= n; i++) {
		cin >> gamer[i];
	}
	sort(gamer + 1, gamer + 1 + n, greater<long long>());
	long long ans = 1;
	long long buffer = gamer[1];
	for (int i = 2; i <= n; i++) {
		if (buffer - gamer[i] <= k) {
			ans++;
			buffer = gamer[i];
		}
		else break;
	}
	cout << ans << endl;
	return 0;
}

T7 [Daimayuan]可重排列(C++,字符串)

请按字典序从小到大的顺序输出所有序列,满足序列中有 p 1 p_1 p1 1 1 1, p 2 p_2 p2 2 2 2, . . . ... ... , p n p_n pn n n n

输入格式

第一行一个整数 n n n

第二行 n n n 个整数 p 1 p_1 p1, p 2 p_2 p2,…, p n p_n pn

输出格式

按字典序从小到大的顺序一行一行输出所有满足条件的序列,每行一个序列,相邻两个数字需要用空格隔开。

样例输入

3
1 2 2

样例输出

1 2 2 3 3
1 2 3 2 3
1 2 3 3 2
1 3 2 2 3
1 3 2 3 2
1 3 3 2 2
2 1 2 3 3
2 1 3 2 3
2 1 3 3 2
2 2 1 3 3
2 2 3 1 3
2 2 3 3 1
2 3 1 2 3
2 3 1 3 2
2 3 2 1 3
2 3 2 3 1
2 3 3 1 2
2 3 3 2 1
3 1 2 2 3
3 1 2 3 2
3 1 3 2 2
3 2 1 2 3
3 2 1 3 2
3 2 2 1 3
3 2 2 3 1
3 2 3 1 2
3 2 3 2 1
3 3 1 2 2
3 3 2 1 2
3 3 2 2 1

数据规模

对于 100 100 100% 的数据,保证 1 ≤ n ≤ 9 1≤n≤9 1n9, 1 ≤ p i ≤ 9 1≤p_i≤9 1pi9,保证满足条件的序列个数不超过 1 0 5 10^5 105 个。

解题思路

这里我们隆重介绍一个新的偷懒工具,next_permutationprev_permutation

传入的参数是数组的起止位置指针,功能是对数组本身操作,得到下一个/上一个字典序排列

然后怎么做就不用我说了吧 q w q qwq qwq

AC代码如下

#include <iostream>
#include <algorithm>
using namespace std;

void read(string& str) {
	int n1, n2;
	cin >> n1;
	for (int i = 1; i <= n1; i++) {
		cin >> n2;
		str.append(n2, i + '0');
	}
}

int main() {
	string str = ""; read(str);
	int len = str.size();
	do {
		for (int i = 0; i < len; i++) printf("%c ", str[i]);
		printf("\n");
	}
	while (next_permutation(str.begin(), str.end()));
	return 0;
}

T8 [Daimayuan]进制转换(C++)

题面

让我看看是谁不会进制转换,哦原来是我


以不同进制的形式输入 n n n 个非负整数,求出它们的和并以 m m m 进制的形式输出。

使用大写字母 A ~ Z 依次代表 10 10 10 ~ 35 35 35, 小写字母 a ~ z 依次代表 36 36 36 ~ 61 61 61

输入格式

第一行输入两个整数 1 ≤ n ≤ 10 1≤n≤10 1n10 2 ≤ m ≤ 62 2≤m≤62 2m62

接下来 n n n 行,每行输入一个整数 2 ≤ t ≤ 62 2≤t≤62 2t62, 一个 t t t 进制数 0 ≤ x ≤ 1 0 9 0≤x≤10^9 0x109

输出格式

一个 m m m 进制数,为最终的结果

输入样例1

2 2
2 1
6 10

输出样例1

111

输入样例2

1 10
52 aA0

输出样例2

97864

输入样例3

2 52
36 AMD
52 YES

输出样例3

dJD

解题思路

由任意进制转换为十进制:

遍历每一位上的数字,乘以其位权重,累加

由十进制转换为任意进制:

对十进制数进行取模,余数插入转换后结果的左侧,然后将十进制数除以 10 10 10,循环操作直到十进制数为 0 0 0

AC代码如下

#include <iostream>
#include <map>
#include <string>
using namespace std;
const int max_n = 10;
const int max_m = 62;
const int max_t = 62;
const int max_len = 64;
const string sign_set = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

int n, t;
long long m;
string num;
map<char, int>convert;
char output[max_len + 1];


void init() {
	int len = sign_set.size();
	for (int i = 0; i < len; i++) {
		convert.insert(pair<char, int>(sign_set[i], i));
	}
}


int main() {
	init();
	cin >> n >> m;
	long long decimal = 0;
	for (int i = 0; i < n; i++) {
		cin >> t >> num;
		int p = 1;
		int len = num.size() - 1;
		for (int i = len; i >= 0; i--) {
			decimal += (long long)(convert[num[i]] * p);
			p *= t;
		}
	}
	int idx = max_len - 1;
	while (decimal != 0) {
		output[idx--] = sign_set[decimal % m];
		decimal /= m;
	}
	cout << &(output[++idx]) << endl;
	return 0;
}

T9 [Daimayuan]循环子串(C++,字符串)

题目描述

一个字符串 S S S是另一字符串 T T T的循环子串当且仅当存在 k k k, T T T所有字符循环右移 k k k位后得到的新串 T ′ T′ T,满足 S S S T ′ T′ T的子串。

例如: abccefab的循环子串。 (cefab循环右移 2 2 2位得到abcef, abcabcef的子串)

一个串 P P P是完全循环串当且仅当对于它的任一子串 H H H, 都有 H r e v e r s e Hreverse Hreverse P P P的循环子串 ( H r e v e r s e Hreverse Hreverse H H H的倒转, 如abc r e v e r s e reverse reverse后 为cba)。

给一个长度为 n n n的字符串, 判断它是不是完全循环串。

输入格式

第一行一个正整数 t t t, 表示测试数据组数。

对于每一组数据,第一行一个正整数 n n n, 表示字符串的长度。接下来一行一个长度为 n n n的字符串. 仅包含小写字母。

输出格式

对于每组测试数据,如果这个串是完全循环串, 输出YES,否则输出NO。每组测试数据之间输出换行。

数据范围

对于所有数据 有 1 ≤ t ≤ 100 1≤t≤100 1t100, 1 ≤ n ≤ 1 0 3 1≤n≤10^3 1n103, ∑ n ≤ 1 0 3 \sum n≤10^3 n103

样例输入

2
4
ccca
11
eeaafbddfaa

样例输出

YES
NO

提示

  1. 本道题目只需要语法知识就可以解决。

  2. 任意子串是什么意思呢?

  3. 如果一个子串包含另一个子串,那么我们是不是只需要求出大子串的合法情况,就可以推出小子串的合法情况。

  4. 从大的子串向小的子串考虑 最大的子串是什么呢?

解题思路

假设abc是循环子串,那么cba也应该是循环子串,则有***abc***cba***

*注:这里将abccba调换也可以,*的数量可以是任意的

进一步假设abcd是循环子串,则有***abcd*dcba***

不难发现,如果abcd是循环子串,则abc自然也是循环子串

所以我们只需要证明最大的循环子串符合条件即可

也就是将给定字符串反转,然后寻找其是否存在

而对于可以循环右移的字符串,我们只需要将其复制然后拼接,在处理之后的字符串中寻找即可

AC代码如下

#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
const int max_t = 100;
const int max_n = 1e3;

string str;
int t, len;

int main() {
	cin >> t;
	for (int i = 0; i < t; i++) {
		cin >> len >> str;
		string rev = str;
		reverse(rev.begin(), rev.end());
		str = str + str;
		if (str.find(rev) != -1)
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
	return 0;
}

T10 [Daimayuan]饿饿 饭饭之暑假大狂欢(C++,数学)

故事接着《饿饿 饭饭 2》,又过了几个月,暑假来啦!!!

这天, c c cc cc和他的小伙伴们决定一起去游乐园玩,他们一天将游乐园的所有设施玩了个遍,甚至大摆锤,过山车他们还去了很多次,愉快的时间总是很短暂的,很快时间就来到了晚上,但是你以为一天的娱乐时光就这样结束了吗,那你就猜错啦。

晚上,游乐园晚上的 p a r t y party party就开始啦,其中有一个游戏环节,赢的人可以得到免费的西瓜,饿到不行的 c c cc cc和他的小伙伴非常希望得到这个西瓜。

包括 c c cc cc和他的小伙伴,有 t t t个玩家参与了这个游戏,每个玩家都有一张带有数字的卡片。第 i i i张卡片上有 n i n_i ni个数字,分别是 m 1 , m 2 , . . . m n m_1,m_2,...m_n m1,m2,...mn

游戏过程中,主持人从袋子里一个一个地取出编号的球。 他用洪亮而清晰的声音大声念出球的编号,然后把球收起来。 如果玩家的卡片上有对应的数字,就可以将它划掉。 最先从他的卡片上划掉所有数字的人获胜。 如果多人同时从他们的卡片上划掉所有数字,那么这些人都不能赢得比赛。 在游戏开始时,袋子里有 100 100 100 个球,编号从 1 1 1 100 100 100,所有球的编号都是不同的。

c c cc cc偷偷知道了每个玩家的数字。 想请你确定每个玩家是否可以在最有利于他的情况下赢得比赛。

输入格式

第一行给出一个数 t t t,代表 t t t个玩家。

接下来第二行到 t + 1 t+1 t+1行,每行第一个数为 n i n_i ni,代表这个人手中有 n n n个卡片,接下来给出序列 a 1 . . . a n a_1...a_n a1...an表示这个人所拥有的卡片的数字。

输出格式

输出 t t t行,每一行给出第 i i i个人在最有利的情况下是否能赢得比赛,可以输出YES, 不可以输出NO

数据范围

1 ≤ t ≤ 100 , 1 ≤ n ≤ 100 , 1 ≤ m i ≤ 100 1≤t≤100,1≤n≤100,1≤m_i≤100 1t100,1n100,1mi100

样例输入

3
1 1
3 2 4 1
2 10 11

样例输出

YES
NO
YES

解题思路

不难发现,如果有一个人不能获胜,那么一定是有其他人的数字集合是他的子集(注:由于可以一次性划去多个数字,重复个数字直接按单个数字处理即可)

那么采用最简单的判断思路——暴力搜索

计算一下时间复杂度:最多需要判断 100 100 100个人,对于每个人需要搜索其余 99 99 99个人,每人最多有 100 100 100个数字,所以时间复杂度上限是 1 0 6 10^6 106,可以接受

所以我们可以采用二维bool数组存储每一个人数字,然后进行||的操作:

num_arr[i][k] != (num_arr[i][k] || num_arr[j][k])

当且仅当num_arr[i][k]没有k数字(为 f a l s e false false),且num_arr[j][k]k数字(为 t r u e true true)时表达式为真

如果表达式为真,就可以停止判断了,因为二者有不同的元素;如果表达式始终为假,那么就说明j的数字集合是i的子集,i不可能获胜

AC代码如下

#include <iostream>
using namespace std;
const int max_n = 100;
const int max_len = 100;

bool num_arr[max_n + 1][max_len + 1];
int n, m;


int main() {
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> m;
		int num;
		for (int j = 0; j < m; j++) {
			cin >> num;
			num_arr[i][num] = true;
		}
	}

	for (int i = 1; i <= n; i++) {
		bool win = true;
		for (int j = 1; j <= n; j++) {
			if (i == j) continue;
			int k;
			for (k = 1; k <= max_len; k++) {
				if (num_arr[i][k] != (num_arr[i][k] || num_arr[j][k])) {
					break;
				}
			}
			if (k == max_len + 1) {
				win = false;
				break;
			}
		}
		if (win) cout << "YES" << endl;
		else cout << "NO" << endl;
	}
	return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/5289.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【Redis】十大数据类型(下篇)

文章目录redis位图(bitmap) --- 底子还是string基本命令图示setbit key offset value setbit 键 偏移位 只能零或者1getbit key offset 查看获取字符串长度 strlen统计key中包含1的个数 bitcount keybitop 统计两个比特key是否都为1技术落地&#xff1a;打卡签到&#xff0c;频…

【C语言蓝桥杯每日一题】——等差数列

【C语言蓝桥杯每日一题】——等差数列&#x1f60e;前言&#x1f64c;等差数列&#x1f64c;解题思路分析&#xff1a;&#x1f60d;解题源代码分享&#xff1a;&#x1f60d;总结撒花&#x1f49e;&#x1f60e;博客昵称&#xff1a;博客小梦 &#x1f60a;最喜欢的座右铭&…

让ChatGPT帮我写shell脚本, 结局很感人

七问ChatGPT, 剑指shell脚本编写 step1: 初问step2: 再问step3: 三问step4: 四问step5: 五问step6: 问个derstep7: 解决问题step8: 小问一下关于ChatGPT思考昨天浏览一篇关于脚本的技术文章的时候, 偶然看见一篇文章中写道关于mysql备份的脚本. 但是这个脚本时基于本地的MySQL服…

Idea+maven+spring-cloud项目搭建系列--13 整合MyBatis-Plus多数据源dynamic-datasource

前言&#xff1a;对于同一个系统&#xff0c;不同的租户需要自己独立分隔的数据库&#xff08;每个数据库的表结构可以是相同的&#xff09;&#xff0c;同时也要支持跨数据源的查询&#xff1b;并且支持分布式事务&#xff0c;如果这里不使用分库分表插件&#xff0c;需要怎样…

使用dd复制将乌班图系统(Ubuntu22.04)完整迁移到新硬盘并扩容

我的折磨历程 开始的时候用乌班图的时候&#xff0c;不懂事&#xff0c;根目录太小了&#xff0c;后来就满了&#xff0c;就就感觉完全没法用&#xff0c;看着现在硬盘贼便宜&#xff0c;去狗东买了个新的硬盘。感觉挂载硬盘并不能解决我的问题&#xff0c;最后选择了保留系统数…

ython和PyTorch实现ChatGPT批量AI智能写作

怎么实现用chatgpt批量写作 ChatGPT是一种针对文本生成的自然语言处理工具&#xff0c;它可以用于生成大量的文本内容。但是&#xff0c;由于ChatGPT需要的计算资源较大&#xff0c;处理时间较长&#xff0c;因此在批量写作时需要考虑花费的时间和资源。 以下是一些步骤&…

又一个免费GPT-4工具 Cursor,程序员写代码将被颠覆

每天都被openai震撼到&#xff0c; 他们家被广为人知的产品是chatgpt&#xff0c;就是那个聊天工具。现在已经开始有越来越多的产品集成openai&#xff0c;比如微软的office&#xff0c;bing。现在又一个工具出现&#xff0c;一个叫Cursor的编辑器已经集成了openai的GPT-4&…

Spring系列(六) --- SpringBoot 与 Servlet 的比较及 Spring 读取配置文件的方式

SpringSpringBoot VS ServletSpring 读取配置文件的方式yml 和 properties 的区别SpringBoot VS Servlet Spring 读取配置文件的方式 1 Value 注解获取单个配置项 如在 yml 中定义一个 qq 音乐的 token; 然后输出, 如下: 2 针对对象的读取: ConfigurationProperties 在 yml 中…

YOLOv5添加辅助训练头

1. 介绍 思路 添加 Aux head 的主要原因是让网络中间层学到更多信息,有更丰富的梯度信息帮助训练。这里要注意,好的梯度信息能够让相同参数量的网络学的更好。 作者原文为: By letting the shallower auxiliary head directly learn the information that lead head has l…

【C#基础】泛型的概念?有什么例子?在游戏中有什么可以使用的地方?

概念 让chatGpt来为我们讲解。 在C#中&#xff0c;泛型是一种允许开发人员编写可重用代码&#xff0c;可以处理多种数据类型的特性。 使用泛型&#xff0c;可以创建类、方法、接口和委托这种不属于任何特定数据的类型&#xff0c;但可以处理满足某些约束条件的任何数据类型。…

手机银行评测系列:北京银行“京彩生活”7.0从用户视角出发,实现沉浸式体验重塑

易观&#xff1a;2023年3月28日&#xff0c;北京银行发布“京彩生活”APP 7.0版本&#xff0c;从旅程再造、特色金融、场景生态、平台联动、协同经营、体验管理和安全守护七大方面全面升级&#xff0c;从用户视角出发&#xff0c;重塑用户旅程&#xff0c;简化操作流程&#xf…

PDF Extra(安卓)

首先&#xff0c;软件是一个一体化的扫描仪和编辑器&#xff0c;工具主要包含有编辑&#xff0c;创建&#xff0c;转换&#xff0c;阅读和查看&#xff0c;其它等等多个功能类型。 编辑里面包含有编辑文本和图像&#xff0c;填写并签署&#xff0c;组织页面&#xff0c;压缩&am…

PLG 基础概念和关键点

什么是 PLGPLG 是 Product Led Growth 的缩写&#xff0c;常翻译为产品增长或产品主导型增长。这个概念最早是风投公司 OpenView 2016年提出的。定义&#xff1a;PLG 是一个聚焦终端用户的增长模型&#xff0c;依赖于产品自身作为获取、转化、扩展客户的核心动力。• 以产品来驱…

入行软件测试7年,才知道原来字节跳动这么容易进

当前就业环境&#xff0c;裁员、失业消息满天飞&#xff0c;好像有一份工作就不错了&#xff0c;更别说高薪了。其实这只是一方面&#xff0c;而另一方面&#xff0c;各大企业依然求贤若渴&#xff0c;高技术人才依然紧缺&#xff0c;只要你技术过硬&#xff0c;拿个年薪50w不是…

vue3快速上手

Vue3快速上手 1.Vue3简介 2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号&#xff1a;One Piece&#xff08;海贼王&#xff09;耗时2年多、2600次提交、30个RFC、600次PR、99位贡献者github上的tags地址&#xff1a;https://github.com/vuejs/vue-next/release…

核心 Android 调节音量的过程

核心 Android 系统提供的调节音量的方法 核心 Android 系统提供了多种调节音量的方法&#xff0c;这些方法主要包括如下这些。 如在 Android Automotive 调节音量的过程 中我们看到的&#xff0c;CarAudioService 最终在 CarAudioDeviceInfo 中 (packages/services/Car/servi…

开源DataX集成可视化项目Datax-Web的使用

上一篇文章我们已经搭建好了 Datax-Web 后台&#xff0c;这篇文章我们具体讲一下如何通过Datax-Web来配置&#xff0c;同步MySQL数据库。 目标 MySql数据库全量同步 1.执行器配置 1、"调度中心OnLine:"右侧显示在线的"调度中心"列表, 任务执行结束后, 将会…

红黑树、B树以及B+树及应用

目录 一.二叉查找树(二叉搜索树&#xff0c;BST) 1.1查找操作 1.2插入操作 1.3删除操作 1.4支持重复数据的二叉查找树 1.5二叉查找树的性能分析 二.平衡二叉查找树 2.1定义 2.2红黑树 2.3为什么红黑树这么受欢迎 三.哈希表为什么不能替代二叉查找树 四.MySQL数据库索…

基于springboot实现学生综合成绩测评系统【源码】分享

基于springboot实现学生综合成绩测评系统演示开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包…

机器学习模型部署PMML

PMML 简介 预测模型标记语言PMML&#xff08;Predictive Model Markup Language&#xff09;是一套与平台和环境无关的模型表示语言&#xff0c;是目前表示机器学习模型的实际标准。从2001年发布的PMML1.1&#xff0c;到2019年最新4.4&#xff0c;PMML标准已经由最初的6个模型…
最新文章