北京信息科技大学第十二届程序设计竞赛暨ACM选拔赛

爱丽丝的人偶(一)
链接:https://ac.nowcoder.com/acm/contest/12226/A
来源:牛客网

题目描述
爱丽丝有个人偶,每个人偶的身高依次是
现在她要将这个人偶摆成一排。
但是人偶被设置了魔法。假设对一个非两端的(不在队首也不在队尾)人偶而言,她相邻的两个人偶,一个比高、一个比矮,那么就会爆炸。
爱丽丝想找到一种摆法,使得所有人偶都不会爆炸。你能帮帮她吗?
输入描述:
一个正整数
输出描述:
满足要求的一种摆法。如果有多解,输出任意一种摆法即可。

示例1
输入
复制
3
输出
复制
1 3 2
说明
对于第二个人偶,她两边的两个人偶都比她矮,满足要求。
另外,[3 1 2]、 [2 1 3] 、[2 3 1]这三种摆法也都满足要求。输出这三种摆法也视为正确。

最直观的想法就是一大一小,所以对半分开然后依次跟着即可

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
//#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(int x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 2e5 + 10;
const int M = 3 * N;
const int mod = 998244353;
const int PP = 131;
const int inf = 0x3f3f3f3f;
//const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

signed main(){
	ios;
	int n;
	cin >> n;
	int temp1 = (n + 1) / 2;
	int temp2 = temp1 + 1;
	
	for (int i = 1; i <= temp1; i ++){
		cout << i << " " ;
		if (temp1 + i <= n)    cout << temp1 + i << " ";
	}
	
	cout << endl;
	
    return 0;
}

爱丽丝的人偶(二)
链接:https://ac.nowcoder.com/acm/contest/12226/B
来源:牛客网

题目描述
爱丽丝有个人偶,第 个人偶的型号为。
现在爱丽丝要拿出其中个人偶,满足这个人偶的型号互不相同。
爱丽丝想知道自己有多少多不同的方案数?
注:若两个人偶的型号相同,那么无论拿她们中的哪一个都是等价的。
请将方案数对取模。
输入描述:
第一行输入两个正整数和,用空格隔开。
第二行输入个正整数,代表这个人偶的型号。
输出描述:
一个整数,代表最终方案的数量对取模的值。

示例1
输入
复制
5 2
1 2 3 2 1
输出
复制
3
说明
一共有{1,2}{1,3}{2,3}这三种不同的方案(型号组合)。
请注意,拿第一个和第三个、第三个和第五个最终的型号组合都是{1,3},被视为同一种方案。

有多少个不同的人偶,需要多少个,组合数即可

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(int x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 2e5 + 10;
const int M = 3 * N;
const int mod = 1e9 + 7;
const int PP = 131;
const int inf = 0x3f3f3f3f;
//const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int n, k;
set<int> ss;
int cnt;

int qmi(int a, int b){
	int res = 1 % mod;
	while(b){
		if (b & 1)   res = res % mod * a % mod;
		a = a % mod * a % mod;
		b >>= 1;
	}
	return res;
}

int C(int a, int b){
	if (b > a)   return 0ll;
	if (a == b)   return 1ll;
	int ans = 1;
	for (int i = a, j = 1; i > a - b; i --, j ++){
		ans = ans % mod * i % mod;
	//	cout << ans << "---" << j << endl;
		ans = ans % mod * qmi(j, mod - 2) % mod; 
		//cout << ans << endl;
	}
	return ans % mod;
}

signed main(){
	
	//ios;
	//cout << qmi(2, 3) << endl;
	//cout << qmi(2, 30) << endl;
	cin >> n >> k;
	for (int i = 1; i <= n; i ++){
		int x;
		cin >> x;
		ss.insert(x);
	}
	
	cnt = ss.size();
	
//	cout << cnt << "---" << k << endl;
	
	cout << C(cnt, k) % mod << endl;
	
    return 0;
}

打毛玉大赛
链接:https://ac.nowcoder.com/acm/contest/12226/C
来源:牛客网

题目描述
灵梦和萃香正在神社进行打毛玉的比赛。
初始有2只毛玉,它们的血量为和。
两个人轮流行动。灵梦先手。
每回合灵梦可以使用封魔阵,对某一只毛玉造成1点伤害。而萃香能使用户隐山投,对某一只毛玉造成任意点伤害。
两人约定,击杀最后一只毛玉的一方获胜。
假设双方都足够聪明,谁会获得最终的胜利?
输入描述:
两个正整数和,用空格隔开。

输出描述:
如果灵梦获胜,则输出一个字符’A’。
如果萃香获胜,则输出一个字符’B’。
示例1
输入
复制
1 2
输出
复制
A
说明
灵梦先攻击血量为2的毛玉,这时无论萃香击杀哪一只毛玉,灵梦都可以击杀另一只,所以灵梦必胜。
示例2
输入
复制
1 1
输出
复制
B
说明
无论灵梦击杀第一只还是第二只,萃香都能击杀另外一只毛玉。

只能造成一点伤害的肯定有劣势,发现只有1 2 这种情况才有可能赢

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(int x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 2e5 + 10;
const int M = 3 * N;
const int mod = 1e9 + 7;
const int PP = 131;
const int inf = 0x3f3f3f3f;
//const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

signed main(){
	ios;
	int a, b;
	cin >> a >> b;
	if (a == 1 && b == 2)      cout << "A" << endl;
	else if (a == 2 && b == 1)  cout << "A" << endl;
	else   cout << "B" << endl;
	
    return 0;
}

贪玩的二小姐(续)
链接:https://ac.nowcoder.com/acm/contest/12226/D
来源:牛客网

题目描述
芙兰朵露拿到了一个只含有 ‘(’ 和 ‘)’ 这两种字符的字符串。芙兰想玩一玩这个字符串。

现在将字符串括号匹配定义如下:

空字符串: “” 是匹配的。
若字符串是匹配的,那么 “(s)” 是匹配的。
若字符串和都是匹配的,字符串 “st” 是匹配的。
例如,"(()())" 是匹配的 , "())(()"则不是匹配的。
芙兰朵露每一次操作可以将括号翻转,即把左括号变成右括号,或者把右括号变成左括号。
她想知道将给定的字符串变成匹配的,需要最少的操作次数是多少?

输入描述:
第一行一个正整数,代表给定字符串的长度。(1\leq{n}\leq 10^6)(1≤n≤10
6
)
第二行是一个长度为的、仅含有 '( '和 ‘)’ 这两种字符的字符串。
输出描述:
如果能在有限次操作将字符串变成匹配的,请输出最少的操作次数。
否则输出-1
示例1
输入
复制
4
()))
输出
复制
1
说明
将第三个括号翻转,字符串变成 “()()” ,为匹配的。
示例2
输入
复制
1
(
输出
复制
-1
说明
翻转后字符串变成")",显然不可能匹配。

一搬这种匹配类型的题很容易想到用栈来实现,但是我这里的思路是从前到后枚举,统计左括号和右括号出现的次数,如果右括号多于左括号的话,那么这个右括号是一定要变成左括号的,枚举完成后还要看左括号是否多余一半,把多的变成右括号

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(int x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 2e5 + 10;
const int M = 3 * N;
const int mod = 1e9 + 7;
const int PP = 131;
const int inf = 0x3f3f3f3f;
//const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

signed main(){
	ios;
	int n;
	cin >> n;
	string str;
	cin >> str;
	if (n & 1){
		cout << "-1" << endl;
	}
	else{
		int ans = 0;
		int cnt_zuo = 0, cnt_you = 0;
		for (int i = 0; i < n; i ++){
			if (str[i] == '('){
				cnt_zuo ++;
			}
			else{
				cnt_you ++;
				if (cnt_you > cnt_zuo){
					cnt_you --;
					cnt_zuo ++;
					ans ++;
				}
			}
		}
		
					
			if (cnt_zuo >= n / 2){
				ans += (cnt_zuo - (n / 2));
			}
			
			cout << ans << endl;
	}
	
    return 0;
}

游戏机本当下手
链接:https://ac.nowcoder.com/acm/contest/12226/E
来源:牛客网

题目描述
藤原妹红拿到了一个游戏机,游戏机上有’1’和’0’两个按钮。
妹红发现,只要按住某个按钮不放,屏幕上就能一直不断打印那个字符。
比如对于"11111111100000000001111111111",只需要按住1、再按住0、再按住1就可以打印出来了。这样妹红最少只需要按3次按钮就可以打印这个字符串。
现在妹红拿到了一个01字符串,她想截取其中的一个子串,这个子串最少按 次按钮就可以打印出来。
(01字符串指仅由字符’0’和字符’1’组成的字符串)
注意这里“最少按 次”的含义是:按 次可以打印出这个子串,但按 次就一定打印不出这个子串。
妹红想知道,一共有多少子串符合要求?
注:一个字符串的子串为该字符串删掉前面和后面部分字符(也可以不删)生成的字符串。
两个子串只要在字符串中位置不同则认为是不同的(哪怕字符串相等)。
输入描述:
第一行两个正整数 和 ,分别代表字符串的长度、和妹红按下按钮的次数。
第二行为一个仅由字符“0”和“1”组成的字符串。
输出描述:
妹红至少按 次就能按出来的子串的数量。
示例1
输入
复制
6 2
001100
输出
复制
8
说明
注意到k=2,因此要寻找最少按2次就能打印的子串。
s[0,2]=“001”,妹红最少按2次就能按出来,先按0再按1。
s[0,3]=“0011”,妹红最少按2次就能按出来,先按0再按1。
s[1,2]=“01”,妹红最少按2次就能按出来,先按0再按1。
s[0,3]=“011”,妹红最少按2次就能按出来,先按0再按1。
s[2,4]=“110”,妹红最少按2次就能按出来,先按1再按0。
s[2,5]=“1100”,妹红最少按2次就能按出来,先按1再按0。
s[3,4]=“10”,妹红最少按2次就能按出来,先按1再按0。
s[3,5]=“100”,妹红最少按2次就能按出来,先按1再按0。
共有8个子串符合要求。
示例2
输入
复制
3 1
110
输出
复制
4
说明
注意到k=1,因此要寻找按1次就能打印的子串。
s[0,0]=“1”,妹红按住1就可以打印出来,只按了1次按钮
s[0,1]=“11”,妹红按住1就可以打印出来,只按了1次按钮
s[1,1]=“1”,妹红按住1就可以打印出来,只按了1次按钮
s[2,2]=“0”,妹红按住0就可以打印出来,只按了1次按钮
共有4个子串符合要求。
备注:
对于20%的样例,
对于40%的样例,
对于60%的样例,
对于100%的样例,

统计每次相同的字符出现了多少次,把这些出现的次数依次放入,然后枚举k个不同的串,可以发现这k个字串的第一个可以选出现次数种,最后一个也可以选出现次数种,乘积即可,注意的是这种求法的前提是由两种以上,所以需要特殊判断k为1的情况

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(int x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 1e6 + 10;
const int M = 3 * N;
const int mod = 1e9 + 7;
const int PP = 131;
const int inf = 0x3f3f3f3f;
//const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

signed main(){
	ios;
	int n, k;
	string str;
	cin >> n >> k;
	cin >> str;
	
	vector<int> v;
	int cnt = 1;
	for (int i = 1; i < str.size(); i ++){
		if (str[i] != str[i - 1]){
			v.push_back(cnt);
			cnt = 1;
		}
		else     cnt ++;
	}
	
	v.push_back(cnt);
	
//	for (int i = 0; i < v.size(); i ++)   cout << v[i] << endl;
	
	if (k == 1){
		int ans = 0;
		for (int i = 0; i < v.size(); i ++){
			int p = v[i];
			ans += (p * (p + 1) / 2);
		}
		cout << ans << endl;
	}
	else{
			int ans = 0;
	for (int i = k - 1; i < v.size(); i ++){
		int cnt1 = 0, cnt2 = 0;
		cnt1 = v[i - k + 1];
		cnt2 = v[i];
		
		ans += (cnt1 * cnt2);
	}
	
	cout << ans << endl;
	}
	
    return 0;
}

宵暗的妖怪
链接:https://ac.nowcoder.com/acm/contest/12226/F
来源:牛客网

题目描述
露米娅作为宵暗的妖怪,非常喜欢吞噬黑暗。
这天,她来到了一条路上,准备吞噬这条路上的黑暗。
这条道路一共被分为部分,每个部分上的黑暗数量为。
露米娅每次可以任取 连续的 未被吞噬过的 三部分,将其中的黑暗全部吞噬,并获得中间部分的饱食度。
露米娅想知道,自己能获得的饱食度最大值是多少?
输入描述:
第一行一个正整数,代表道路被分的份数。
第二行有个正整数,代表每一部分黑暗数量。
数据范围:
输出描述:
一个正整数,代表最终饱食度的最大值。
示例1
输入
复制
7
2 4 1 4 2 1 8
输出
复制
6
说明
选择[2,4,1]和[4,2,1]这两段即可。饱食度为4+2=6。
示例2
输入
复制
7
2 4 1 7 2 1 8
输出
复制
7
说明
选择[1,7,2]这一段即可。饱食度为7。
值得注意的是,若取两段进行吞噬,反而最多只能获得6的饱食度,并不是最大的。

很明显是动态规划,为什么可以直接选前3个,而不用依次枚举前多少个,因为前3个也可以从前4个更新

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(int x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 1e5 + 10;
const int M = 3 * N;
const int mod = 1e9 + 7;
const int PP = 131;
const int inf = 0x3f3f3f3f;
//const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int b[N], a[N];
int f[N];
int n;

signed main(){
	ios;
	cin >> n;
	for (int i = 1; i <= n; i ++)   cin >> b[i];
	
	for (int i = 3; i <= n; i ++){
		a[i] = (b[i - 1]);
	}	
	
	for (int i = 3; i <= n; i ++){
		f[i] = max(f[i], f[i - 1]);
		f[i] = max(f[i], f[i - 3] + a[i]);
	}
	
	cout << f[n] << endl;
	
    return 0;
}

魔界伊始
链接:https://ac.nowcoder.com/acm/contest/12226/G
来源:牛客网

题目描述
神崎作为魔界之神,造人的方法是用沙子捏成人形,然后用魔法赋予其意识。
神崎有一台天平以及个砝码,另外她还有很多个同样重的烧杯和无穷多的沙子。平日她通过这些来称量出准确重量的沙子。
她想知道能否利用这些砝码称出重量为的沙子?
一共有次询问。
注:烧杯的数量可以视为无穷多个。烧杯的重量是未知的,但大小可以视为无穷大,即可以装任意多的沙子。烧杯中也可以放砝码。
输入描述:
第一行一个正整数。
第二行有个正整数,代表砝码的重量。
接下来的一行有一个正整数。
接下来的行,每一行有一个正整数,分别代表一次询问。
数据范围:1≤q,n≤100000,1≤a_i,x≤10^{18}1≤q,n≤100000,1≤a
i

,x≤10
18

输出描述:
输出行。如果能撑出重量为的沙子,则输出"Yes"。否则输出"No"(不包含引号)。
示例1
输入
复制
2
6 20
2
8
7
输出
复制
Yes
No

想要称出重量为8的沙子,可以先用两个砝码称出重量14的沙子,然后用这些沙子和一个重量6的砝码称出重量8的沙子。
但是无论如何,显然都不能称出重量7的沙子。

很明显一个沙子能否被称量的出来,只需要看这个沙子能否被那些砝码的各种加的,减的任意组合构成,而一些数乱减最后会得到什么数,会得到这些数的最大公约数,根据辗转相除法,然后那些加也一定是那个最大公约数的倍数

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(int x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 1e5 + 10;
const int M = 3 * N;
const int mod = 1e9 + 7;
const int PP = 131;
const int inf = 0x3f3f3f3f;
//const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int gcd(int a, int b){
	return b ? gcd(b, a % b) : a;
}
int a[N];

signed main(){
	ios;
	int n;
	cin >> n;
	
	cin >> a[1];
	int temp = a[1];
	for (int i = 2; i <= n; i ++){
		cin >> a[i];
		temp = gcd(temp, a[i]);
	}
	
	int q;
	cin >> q;
	while(q --){
		int x;
		cin >> x;
		if (x % temp == 0)   cout << "Yes" << endl;
		else   cout << "No" << endl;
	}

    return 0;
}

芭芭拉冲鸭~
链接:https://ac.nowcoder.com/acm/contest/12226/H
来源:牛客网

题目描述
芭芭拉拿到了一棵无根树,树上每个节点被染成了红色或绿色或蓝色。(R=红色,G=绿色,B=蓝色)。
任意两点之间的距离均为1。
若一条边连接的两个节点的颜色不同,芭芭拉则可以在这条边上冲刺。
但是,芭芭拉在冲刺的时候不能掉头。例如芭芭拉已经从冲到了,就不能再回到。
现在芭芭拉想知道,自己在这棵树上最远能冲刺的距离是多少?
输入描述:
第一行一个正整数,代表树的节点个数。
第二行是一个长度为的字符串,仅由"R、G、B"这三种字符组成。第i个字符用于描述第i个节点的颜色。
接下来的行,每行有两个正整数和,代表和节点有一条边连接。保证输入一定表示一棵树。
输出描述:
一个正整数,代表芭芭拉能冲刺的距离的最大值。
示例1
输入
复制
5
RRGBG
1 2
2 3
3 4
4 5
输出
复制
3
说明
这棵树是一条1-2-3-4-5的链,选择路径2-3-4-5即可。这样芭芭拉直接从2冲到5,冲刺距离为3。
注意1和2的颜色相同,所以芭芭拉并不能在1-2这条边上冲刺。
备注:
对于10%的数据,
对于20%的数据,树退化成了一条链。
对于20%的数据,所有点的颜色都相同。
对于100%的数据,

最远能到达哪里,在一棵树上,很明显就是树的最长直径,只不过分成了块。枚举那个中间点即可

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(int x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 1e6 + 10;
const int M = 3 * N;
const int mod = 1e9 + 7;
const int PP = 131;
const int inf = 0x3f3f3f3f;
//const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int h[N], e[N], ne[N], idx;
string str;
int n;
int ans;
bool st[N];

void add(int a, int b){
	e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}

int dfs(int u, int father){
	st[u] = true;
	
	int dist = 0;
	int d1 = 0, d2 = 0;
	
	for (int i = h[u]; ~i; i = ne[i]){
		int j = e[i];
		if (j == father)   continue;
		int d = dfs(j, u) + 1;
		dist = max(d, dist);
		if (d >= d1)     d2 = d1, d1 = d;
		else if (d > d2)   d2 = d;      
	}
	
	ans = max(ans, d1 + d2);
	
	return dist;
}

signed main(){
	cin >> n;
	cin >> str;
	memset(h, -1, sizeof h);
	
	for (int i = 1; i < n; i ++){
		int a, b;
		cin >> a >> b;
		if (str[a - 1] != str[b - 1]){
			add(a, b);
			add(b, a);
		}
	}
	
	for (int i = 1; i <= n; i ++){
		if (!st[i]){
			dfs(i, -1);
		}
	}
	
	cout << ans << endl;
	
    return 0;
}

永远亭的小游戏
链接:https://ac.nowcoder.com/acm/contest/12226/I
来源:牛客网

题目描述
蓬莱山辉夜由于整天宅在家,整个人都已经变成了一只废neet姬了。于是,她找来了铃仙和因幡帝,来玩一个小游戏。
辉夜拿出一个长度为的数组,铃仙拿出一个长度为的数组,因幡帝拿出一个长度为的数组。
她们等概率的在各自的数组中取一个数。辉夜想知道这三个取出的数的乘积的期望是多少?
可以证明,这个期望一定是有理数,可以写成\frac{x}{y}
y
x

的形式。请输出这个分数对10^9+710
9
+7取模的值。
提示:分数\frac{x}{y}
y
x

对取模的值的意义是在区间里找到一个数满足对取模为。
提示2:本题输入数据较大,推荐使用scanf或更快的输入方式
输入描述:
第一行输入三个正整数,用空格隔开。分别代表辉夜、铃仙和因幡帝拿到的数组长度。
第二行输入个正整数,代表辉夜拿到的数组。
第三行输入个正整数,代表铃仙拿到的数组。
第四行输入个正整数,代表因幡帝拿到的数组。
数据范围:
输出描述:
最后乘积的期望对取模的值。
示例1
输入
复制
2 2 2
1 2
1 1
2 4
输出
复制
500000008
说明
三个人各取一个数的组合有以下8种:
112=2
114=4
112=2
114=4
212=4
214=8
212=4
214=8
(2+4+2+4+4+8+4+8)/8=36/8=4.5
最终的乘积期望是4.5,即9/2,由于(500000008*2)%1000000007=9,因此输出500000008

想一想就能知道三个数组的数分别乘起来然后加起来就是这三个数组的和的乘积,相乘法和加法的原理,然后分数取模就是求逆元

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(int x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 1e5 + 10;
const int M = 3 * N;
const int mod = 1e9 + 7;
const int PP = 131;
const int inf = 0x3f3f3f3f;
//const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int n, m, k;

int qmi(int a, int b){
	int res = 1;
	while(b){
		if (b & 1)   res = res % mod * a % mod;
		a = a % mod * a % mod;
		b >>= 1; 
	}
	return res % mod;
}

signed main(){
	ios;
	int sum1 = 0, sum2 = 0, sum3 = 0;
	cin >> n >> m >> k;
	for (int i = 1; i <= n; i ++){
		int x;
		cin >> x;
		sum1 += x;
		sum1 %= mod;
	}
	
	for (int i = 1; i <= m; i ++){
		int x;
		cin >> x;
		sum2 += x;
		sum2 %= mod;
	}
	
	for (int i = 1; i <= k; i ++){
		int x;
		cin >> x;
		sum3 += x;
		sum3 %= mod;
	}
	
	int zi = (sum1 * sum2) % mod * (sum3) % mod;
	int mu = (n * m % mod * k) % mod;
	
	cout << zi * qmi(mu, mod - 2) % mod << endl;
	
    return 0;
}

芭芭拉冲鸭~(续

链接:https://ac.nowcoder.com/acm/contest/12226/J
来源:牛客网

芭芭拉这次来到了一棵字母树,这同样是一棵无根树,每个节点上面有一个小写字母。
芭芭拉想知道,自己从x冲刺到y,从x走到y收集所有字母,选择其中一部分字母组成一个回文串,这个回文串的最大长度是多少?
同样的,芭芭拉冲刺的时候是不能掉头的。
一共有q次询问。每次的询问是独立的(即本次收集字母不影响之后的询问,每次询问时字母都是未被收集状态)。
输入描述:
第一行有一个正整数。
接下来的行,每行输入两个正整数和,代表和之间有一条无向边相连。
接下来一行有一个长度为的字符串,字符串仅由小写字母构成。第个字符表示节点上的字母。
接下来一行是一个正整数,代表询问次数。
接下来的行,每行两个正整数和。
(保证输入一定是一棵树)

输出描述:
对应每次询问,输出一个正整数,代表回文串的最大长度。
示例1
输入
复制
5
1 2
1 3
2 4
2 5
abcba
3
4 5
1 2
3 3
输出
复制
3
1
1
说明
这棵树的构造如下:

对于第一个询问,芭芭拉冲刺的路径是4-2-5,收集的字母有两个b一个a,可以构建的最长回文串是"bab",长度为3。
对于第二个询问,芭芭拉冲刺的路径是1-2,收集的字母有一个b一个a,可以构建的最长回文串是"a"(也可以是"b"),长度为1。
对于第三个询问,芭芭拉起点和终点都是3,所以站在原地不动,收集的字母有只有一个c,可以构建的最长回文串是"c",长度为1。

首先第一个点,构成的回文串是由中间的字母任意组合的,所以只需要知道那两个点中间每个字母出现的次数就可以了,并不需要知道顺序,任何两个点中间有哪些点可以如何求出,可以用最近公共祖先,如何维护那些字母出现的次数,可以从根节点dfs出走到每个点每个字母出现了多少次,右如何判断两个点间每个字母出现了多少次,先求出最近公共组先,然后分别加上这两个点到祖宗节点的每个祖母的出现次数,然后再减去祖先节点到祖宗节点的每个字母出现的次数,然后再减去祖先节点本身的字母,因为被减去过两次

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(int x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N =1e6 + 10;
const int M = 2 * N;
const int mod = 1e9 + 7;
const int PP = 131;
const int inf = 0x3f3f3f3f;
//const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int n, m, s;
int h[N], e[M], ne[M], idx;
int depth[N], fa[N][30];
int q[N];
char str[N];
int cnt[N][30];
int Fa[N];

void add(int a, int b)
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

void bfs(int root)
{
    memset(depth, 0x3f, sizeof depth);
    depth[0] = 0, depth[root] = 1;
    int hh = 0, tt = 0;
    q[0] = root;
    while (hh <= tt)
    {
        int t = q[hh ++ ];
        for (int i = h[t]; ~i; i = ne[i])
        {
            int j = e[i];
            if (depth[j] > depth[t] + 1)
            {
                depth[j] = depth[t] + 1;
                q[ ++ tt] = j;
                fa[j][0] = t;
                for (int k = 1; k <= 25; k ++ )
                    fa[j][k] = fa[fa[j][k - 1]][k - 1];
            }
        }
    }
}

int lca(int a, int b)
{
    if (depth[a] < depth[b]) swap(a, b);
    for (int k = 25; k >= 0; k -- )
        if (depth[fa[a][k]] >= depth[b])
            a = fa[a][k];
    if (a == b) return a;
    for (int k = 25; k >= 0; k -- )
        if (fa[a][k] != fa[b][k])
        {
            a = fa[a][k];
            b = fa[b][k];
        }
    return fa[a][0];
}

void Dfs(int u, int father){
	Fa[u] = father;
	cnt[u][str[u] - 'a'] ++;
	for (int i = h[u]; ~i; i = ne[i]){
		int j = e[i];
		if (j == father)   continue;
		for (int k = 0; k < 26; k ++){
			cnt[j][k] += cnt[u][k];
		}
		
		Dfs(j, u);
	}
}

signed main(){
	ios;
	memset(h, -1, sizeof h);
	cin >> n;
	for (int i = 1; i < n; i ++){
		int a, b;
		cin >> a >> b;
		add(a, b), add(b, a);
	}
	
	bfs(1);
	cin >> str + 1;
	
	Dfs(1, -1);
	
	cin >> m;
	while(m --){
		int x, y;
		cin >> x >> y;
		int LCA = lca(x, y);
		int sum = 0, odd = 0;
		int Q[26] = {0};
		
		for (int i = 0; i < 26; i ++){
			Q[i] = cnt[x][i] + cnt[y][i] - cnt[LCA][i] - cnt[Fa[LCA]][i];
		}
		
		for (int i = 0; i < 26; i ++){
			sum += (Q[i] / 2 * 2);
			odd |= Q[i] & 1;
		}
		
		cout << sum + odd << endl;
	}
		
    return 0;
}

玩具销售员
链接:https://ac.nowcoder.com/acm/contest/12226/K
来源:牛客网

题目描述
达达利亚是至冬国著名的玩具销售员。
有一天,他进货了个玩具,但里面有个次品。
每次检查他最多挑2个玩具出来进行检查。不过达达利亚慧眼如炬,他一眼就能看到次品的所在。
他想不超过次检查就把所有的次品挑出来,请问他是否可能做到这一点?
输入描述:
三个正整数、、,用空格隔开。
输出描述:
如果达达利亚能在k次检查中挑出所有的次品,输出"Yes"。
否则输出"No"。
(不要输出引号)
示例1
输入
复制
3 3 1
输出
复制
No
说明
一共3个玩具,全部是次品。达达利亚无论怎么挑选都无法在一次检查中成功挑完所有次品
示例2
输入
复制
5 3 2
输出
复制
Yes
说明
一共5个玩具,有3个次品。达达利亚第一次检查挑选一个次品和一个正品,第二次检查挑选两个次品,这样就挑完所有次品了。

贪心判断即可

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <set>
#include <string>
#include <queue>
#include <map>
#include <stack>
#include <map>
#include <unordered_map>
#include <vector>
#include <cmath>
//#include <ext/rope>
#include <bits/stdc++.h> 

using namespace std;
//using namespace __gnu_cxx;

#define gt(x) x = read()
#define int long long
#define ios ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define endl "\n"
//#define x first
//#define y second

int dx[4] = {0, 1, 0, -1};
int dy[4] = {1, 0, -1, 0}; 

//typedef __int128 INT;
typedef pair<double, int> PDI;
typedef pair<int, int> PII;
typedef unsigned long long ULL;

inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}

inline void print(int x) {
  if (x < 0) { putchar('-'); x = -x; }
  if (x >= 10) print(x / 10);
  putchar(x % 10 + '0');
}

const int N = 1e5 + 10;
const int M = 3 * N;
const int mod = 1e9 + 7;
const int PP = 131;
const int inf = 0x3f3f3f3f;
//const int INF = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-10;
const double PI = acos(-1);

int n, m, k;

signed main(){
	ios;
	cin >> n >> m >> k;
	 if (m > 2 * k){
	 	cout << "No" << endl;
	 }
	 else   cout << "Yes" << endl;
	
    return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值