A
链接:https://www.nowcoder.com/acm/contest/134/A
来源:牛客网
题目描述
在数学课上老师教她的三角形知识,她开始从这些木棍中间找三根木棍来组成一个周长最大的三角形,
这时她的兄弟顺溜偷偷的溜了过来,偷走了第i根木棍,现在她想知道现在能够组成周长最大的三角形
的周长是多少?
输入描述:
输出描述:
对于每个询问输出一行表示答案,如果删除木棍后无法组成三角形则输出 -1 。
思路:
按照三角形最长边小于其余两边之和来从长到短选择最长边。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
typedef struct Node{
int v, id;
bool operator < (const Node &rhs) const{
return v < rhs.v;
}
}Node;
vector<Node> p;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n >> k;
p.resize(n);
for(int i = 0; i < n; i++){
cin >> p[i].v;
p[i].id = i;
}
sort(p.begin(), p.end());
while(k--){
int ban;
cin >> ban;
ban--;
ll res = -1;
for(int i = n - 1; i >= 2; i--){
if(p[i].id == ban)
continue;
int sum = 0;
for(int j = i - 1, cnt = 0; j >= 0 && cnt < 2; j--)
if(p[j].id == ban)
continue;
else{
cnt++;
sum += p[j].v;
}
if(sum > p[i].v){
res = (ll)sum + (ll)p[i].v;
break;
}
}
cout << res << endl;
}
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
B
链接:https://www.nowcoder.com/acm/contest/134/B
来源:牛客网
题目描述
给出一个长度为 n 的数列,数列里的每个元素都是个位数,这个数列的每一个连续子数列都能生成
一个十进制数,对于子数列a[l~r],这个十进制数的个位为a[r],十位为a[r - 1],...,最高位
为a[l]。
现在铁子需要知道最小的不能被该数列的子数列生成的十进制非负整数是多少?
输入描述:
第一行一个数字n。(1 ≤ n ≤ 1000) 第二行n个数字di。(0 ≤ di ≤ 9)
输出描述:
输出一个数字表示答案。
思路:
从小到大猜。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
vi p;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n;
p.resize(n);
for(int i = 0; i < n; i++)
cin >> p[i];
bool zero = false;
for(int i = 0; i < n; i++)
if(p[i] == zero){
zero = true;
break;
}
if(!zero)
cout << 0 << endl;
else{
for(int i = 0; ; i++){
bool found = false;
for(int j = n - 1; j >= 0; j--){
int clone = i, t = j;
while(t >= 0 && clone && clone % 10 == p[t]){
t--;
clone /= 10;
}
if(!clone){
found = true;
break;
}
}
if(!found){
cout << i << endl;
break;
}
}
}
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
C
链接:https://www.nowcoder.com/acm/contest/134/C
来源:牛客网
题目描述
培养皿可以被看成一个n*n的方格,最初病菌滴在了这n*n的格子中的某些格子,病菌的传染方式是这样的,如果一个方格与两个或多个被感染的方格相邻(两个方格相邻当且仅当它们只有一条公共边),
那么它就会被感染。现在铁子和顺溜想知道,最终所有的方格会不会都被感染。
输入描述:
第一行两个整数n,m。n表示方格的规格,m表示最初病菌所在的格子数。(1 ≤ n ≤ 1000, 0 < m < n)。
输出描述:
如果最终所有的方格都会被感染,输出 YES。 否则输出 NO。
思路:
可以直观发现,只有当m >= n时才会铺满整个培养皿。
因为只有有两个相邻的感染才能被感染,也就是说如果要让(i,j)感染,i行或者i + 1行必须要有感染的才有可能。
如果m < n,显然无法使得所有行都感染。
如果m == n,放对角线就可以了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n >> m;
if(m >= n)
cout << "YES" << endl;
else
cout << "NO" << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
D
链接:https://www.nowcoder.com/acm/contest/134/D
来源:牛客网
题目描述
输入描述:
第一行三个整数n, m, R(2 ≤ n ≤ 200, 1 ≤ m ≤ 5000, 2 ≤ R ≤ min(n, 15))。 第二行R个整数表示需要去玩耍的郊区编号。 以下m行每行Ai, Bi, Ci(1 ≤ Ai, Bi ≤ n, Ai ≠ Bi, Ci ≤ 10000) 保证不存在重边。
输出描述:
输出一行表示最小的花费
思路:
floyd预处理,然后用dp记录结果枚举。
dp[i][j],i代表此时的状态,j代表最后一次选的点。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
vi p;
vii path, dp;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n >> m >> k;
p.resize(k);
for(int i = 0; i < k; i++){
cin >> p[i];
p[i]--;
}
path.resize(n, vi(n, INF));
for(int i = 0; i < m; i++){
int u, v, c;
cin >> u >> v >> c;
u--;
v--;
path[u][v] = c;
path[v][u] = c;
}
for(int i = 0; i < n; i++)
path[i][i] = 0;
for(int t = 0; t < n; t++)
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
path[i][j] = min(path[i][j], path[i][t] + path[t][j]);
dp.resize(1 << k, vi(k, INF));
for(int i = 0; i < k; i++)
dp[1 << i][i] = 0;
for(int i = 0; i < (1 << k); i++){
for(int j = 0; j < k; j++){
if(!(i & (1 << j)))
continue;
for(int t = 0; t < k; t++){
if((1 << t) & i)
continue;
dp[i | (1 << t)][t] = min(dp[i | (1 << t)][t], dp[i][j] + path[p[j]][p[t]]);
}
}
}
int res = INF;
for(int i = 0; i < k; i++)
res = min(res, dp[(1 << k) - 1][i]);
cout << res << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
E
链接:https://www.nowcoder.com/acm/contest/134/E
来源:牛客网
题目描述
输入描述:
输入只有一行,一个浮点数。保证数据合法,不存在整数位的前导零以及小数位的后导零。
输出描述:
输出只有一行,一个浮点数。
思路:
用来启发人们发现计算机的浮点数是有误差的。
把输入当字符串处理即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
string str;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> str;
cout << str << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
F
链接:https://www.nowcoder.com/acm/contest/134/F
来源:牛客网
题目描述
一串长度为 n 的字符串 A 和一串长度为 m 的字符串 B。并且这两串字符串只会含有 0 或 1 。
铁子可以对字符串 A 执行两种操作,两种操作可以执行任意次。
操作1(无情替换):铁子可以用 11 替换掉 0 ,也可以用 00 替换掉 1 .
操作2(极限删除):铁子可以删除掉 111 ,也可以删除 000 .
现在问,字符串 A 可以变成字符串 B 吗?
输入描述:
第一行有一个整数T,表示有T(1<=T<=1000)组测试数据。 接下来的每组数据,第一行有两个整数n,m(1<=n,m<=100),表示字符串A和字符串B的长度。 接下来有两行字符串,分别表示字符串A和字符串B。
输出描述:
对于每组测试数据,如果字符串A可以变为字符串B,则输出一行”YES”,否则输出一行”NO”.输出不包括引号。
思路:
可以发现顺序是无关的,也就是说001一定可以从100或者010转换而来。
又可以发现,1可以自增成1111(4个1)或者1111111(7个1),也就是说可以自增3n的长度,当然n属于R。
那么现在需要做的就是把A和B都转化成0或者1的串,然后判断他们长度之间的关系。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
string str, ptr;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
int times;
cin >> times;
while(times--){
cin >> n >> m;
cin >> str >> ptr;
int res = 0;
for(int i = 0; i < n; i++)
res += 1 + str[i] - '0';
for(int i = 0; i < m; i++)
res -= 1 + ptr[i] - '0';
if(res % 3)
cout << "NO" << endl;
else
cout << "YES" << endl;
}
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
G
链接:https://www.nowcoder.com/acm/contest/134/G
来源:牛客网
题目描述
------分割线-------------------------------------------------------------
下面是黑白棋规则介绍:
![](https://i-blog.csdnimg.cn/blog_migrate/96e7a4083173ae6f0acb947570ea7635.jpeg)
合法的棋步包括:在一个空格新落下一个棋子,并且翻转对手一个或多个棋子。
下子方式:把自己颜色的棋子放在棋盘的空格上,而当自己放下的棋子在横、竖、斜八个方向内有一个自己的棋子,则被夹在中间的对方棋子全部翻转会成为自己的棋子。夹住的位置上必须全部是对手的棋子,不能有空格。并且,只有在可以翻转棋子的地方才可以下子。
一步棋可以在数个方向上翻棋,任何被夹住的棋子都必须被翻转过来,棋手无权选择不去翻某个棋子必须是刚下的子夹对方才能够翻对方的子,因翻转对方的棋子而夹住的子是不能被翻的。
翻转棋子时,每次下子最少必须翻转对方一个棋子,若棋局中下子都不能翻转对方棋子,则自动pass轮空,己方无子可下,由对方继续下子。两个玩家都不能下子翻转对方棋子,游戏结束。
输入描述:
每行两个数字x,y代表落子坐标(1 ≤ x,y ≤ 8) 以EOF结束下子,保证下子的正确性以及合法性,下完最后一颗子代表棋局结束。 ps:emmmm... 貌似有点长,不要慌,问题不大(雾
输出描述:
输出一行,黑方与白方的棋子数量之比a:b
思路:
有研究黑白棋的朋友吗?
从这题中我感受到了黑白棋的魅力,首先如果棋盘是n*m,那么最多放n*m - 4个棋,而且只要知道放的棋的位置,甚至不用知道先后顺序和颜色,就一定可以复原成唯一的棋盘。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
const int dr[] = {-1, -1, -1, 0, 0, 1, 1, 1};
const int dc[] = {-1, 0, 1, -1, 1, -1, 0, 1};
int n, m, k;
vi x, y, p;
vii mat, inq;
void recur(int depth, int id){
int u, v;
if(depth > (int)x.size())
return;
bool found = false;
for(int i = 0; i < (int)x.size(); i++){
u = x[i];
v = y[i];
if(mat[u][v] >= 0)
continue;
for(int dir = 0; dir < 8; dir++){
int cnt = 0;
int uu = u + dr[dir];
int vv = v + dc[dir];
if(!(uu > 0 && vv > 0 && uu <= 8 && vv <= 8))
continue;
if(mat[uu][vv] == id)
continue;
while(cnt < 3 && uu > 0 && vv > 0 && uu <= 8 && vv <= 8 && mat[uu][vv] >= 0){
cnt |= (1 << mat[uu][vv]);
if(cnt == 3)
break;
uu += dr[dir];
vv += dc[dir];
}
if(cnt == 3){
found = true;
while(u != uu || v != vv){
mat[u][v] = mat[uu][vv];
u += dr[dir];
v += dc[dir];
}
u = x[i];
v = y[i];
}
}
if(found)
return recur(depth + 1, id ^ 1);
}
return recur(depth, id ^ 1);
}
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
mat.resize(10, vi(10, -1));
inq.resize(100, vi(5));
mat[4][4] = mat[5][5] = 0;
mat[5][4] = mat[4][5] = 1;
int u, v;
while(cin >> u >> v){
x.push_back(u);
y.push_back(v);
}
recur(1, 1);
p.resize(2);
for(int i = 1; i <= 8; i++)
for(int j = 1; j <= 8; j++){
if(mat[i][j] < 0)
continue;
p[mat[i][j]]++;
}
cout << p[1] << ":" << p[0] << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
H
链接:https://www.nowcoder.com/acm/contest/134/H
来源:牛客网
题目描述
现在你可以执行以下操作:
·你可以选择任意一个盒子,在选择的盒子内吃掉一个糖果。
对你的要求如下:
·任何m个相邻的盒子内糖果数量不能超过x个。
请问,实现要求的最少操作次数是多少?
输入描述:
第一行三个数字n, m, x(2 ≤ n,m ≤ 106,1 ≤ x ≤ 109)。 第二行n个数字(1 ≤ ai ≤ 109)。
输出描述:
输出一个操作数,代表实现要求的最少操作数。
思路:
利用滑动窗口的想法,从左到右扫描,优先吃掉右边的。
不必害怕是否会退化成(nm), 可以证明,当此时扫到i时,i - m退出,如果此时val[i] > val[i - m]那才有可能要吃,而且只用吃一个。
实际复杂度为O(n)。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
vll p;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n >> m >> k;
p.resize(n + 1);
for(int i = 1; i <= n; i++)
cin >> p[i];
ll cur = 0, res = 0;
for(int i = 1; i <= min(n, m - 1); i++)
cur += p[i];
for(int i = min(n, m); i <= n; i++){
cur += p[i];
for(int j = i; cur > k; j--){
ll cal = min(cur - k, p[j]);
res += cal;
p[j] -= cal;
cur -= cal;
}
cur -= p[i - m + 1];
}
cout << res << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
H
链接:https://www.nowcoder.com/acm/contest/134/I
来源:牛客网
题目描述
输入描述:
第一行一个数字n表示铁子班级的总人数。1≤n≤105 第二行一个字符串s表示最初的队形布置,si=0表示第i个人是女生,si=1表示第i个人是男生。
输出描述:
输出一行表示答案
思路:
思考这样一种情形,可以改变一个人的性格,问最长的连续女生是多少?
这个问题可以转换成上述情形,最后只用输出min(女生总人数,上述情形计算结果)即可;
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
string str;
vii dp;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n;
dp.resize(n, vi(2));
cin >> str;
cerr << str << endl;
int res = 0, cnt = 0;
cnt = dp[0][0] = !(str[0] - '0');
dp[0][1] = 1;
for(int i = 1; i < n; i++){
if(!(str[i] - '0')){
cnt++;
dp[i][0] = dp[i - 1][0] + 1;
dp[i][1] = dp[i - 1][1] + 1;
}
else{
dp[i][0] = 0;
dp[i][1] = dp[i - 1][0] + 1;
}
res = max(res, max(dp[i][0], dp[i][1]));
}
cout << min(res, cnt) << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
J
链接:https://www.nowcoder.com/acm/contest/134/J
来源:牛客网
题目描述
输入描述:
第一行一个整数n表示序列的长度(1≤n≤105) 第二行n个整数ai表示序列的每个整数(1≤ai≤109)
输出描述:
输出一行表示答案
思路:
首先先要理解题意,发现可以除去一个元素,但要加入一个新元素,为了不使新元素有任何影响,让新元素比任何元素大即可。
这样就可以排除新元素的影响, 题意也就可以变成要除去多少个元素使得序列无重复元素。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef vector<int> vi;
typedef vector<vi> vii;
typedef vector<ll> vll;
const int MAXN = 1e6 + 10;
const ll INF = 0x3f3f3f3f;
const ll MOD = 1e9 + 7;
const double eps = 1e-8;
int n, m, k;
vi p;
int main(void)
{
ios::sync_with_stdio(false);
cin.tie(0);
cout << setprecision(10) << fixed;
cin >> n;
p.resize(n);
for(int i = 0; i < n; i++)
cin >> p[i];
sort(p.begin(), p.end());
cout << n - (unique(p.begin(), p.end()) - p.begin()) << endl;
cerr << "execute time : " << (double)clock() / CLOCKS_PER_SEC << endl;
return 0;
}
未来可期。