题目链接:http://codeforces.com/contest/1167
Problem A
暴力就好
代码:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int N = 1e5+5;
char s[110];
int main()
{
int T,n;
scanf("%d",&T);
while (T--){
int n;
scanf("%d",&n);
scanf("%s",s+1);
bool flag = false;
if (n>=11){
for (int i = 1;i<=n-10;i++)
if (s[i]=='8'){
flag = true;
printf("YES\n");
break;
}
}
if (!flag) printf("NO\n");
}
return 0;
}
Problem B
这是一种题型叫交互题
代码参考自大佬的博客 https://blog.csdn.net/weixin_43272781/article/details/90251099
理解一下大概就是:机器预先排序了6个数。
你通过printf询问机器ai*aj等于多少,然后机器通过scanf给出了你询问的结果。
当printf四次也就是询问四次之后,你要能够猜出序列。
简单来说就是printf当做输入,scanf当做输出。
由于“输入”用printf,会比较死,如何printf正确的答案,需要你找到4组合适的询问,保证你一定能printf一个唯一的序列。
总结:有限次printf获取信息,推出正确答案。
然后每个printf后面写一句fflush(stdout);大概就是清空输出在屏幕上东西
代码中next_permutation()函数可以获取字典序更大的全排列。
(pre_permutation()可以得到字典序更小的全排列)
代码:
#include<cstdio>
#include<algorithm>
using namespace std;
int b[4];
int main()
{
printf("? 1 2\n");
fflush(stdout);
scanf("%d",&b[0]);
printf("? 2 3\n");
fflush(stdout);
scanf("%d",&b[1]);
printf("? 4 5\n");
fflush(stdout);
scanf("%d",&b[2]);
printf("? 5 6\n");
fflush(stdout);
scanf("%d",&b[3]);
int a[7] = {0,4,8,15,16,23,42};
while (1){
if (a[1]*a[2]==b[0] && a[2]*a[3]==b[1] && a[4]*a[5]==b[2] && a[5]*a[6]==b[3]){
printf("! %d %d %d %d %d %d\n",a[1],a[2],a[3],a[4],a[5],a[6]);
fflush(stdout);
break;
}
else next_permutation(a+1,a+7);///产生字典序更大的一种排列,或者dfs预处理一下储存所有序列
}
return 0;
}
Problem C
暴力用并查集搞就行
代码:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#define ll long long
using namespace std;
const int N = 5e5+5;
int uf[N];
int a[N];
int cnt[N];
int find1(int x)
{
int r = x;
while (r!=uf[r]) r = uf[r];
for (int i = x,j;i!=r;i=j){
j = uf[i];
uf[i] = r;
}
return r;
}
void join(int a,int b)
{
a = find1(a),b = find1(b);
if (a!=b) uf[a] = b;
}
int main()
{
int n,m;
scanf("%d %d",&n,&m);
for (int i = 1;i<=n;i++) uf[i] = i;
while (m--){
int k,x;
scanf("%d",&k);
for (int i = 1;i<=k;i++){
scanf("%d",&a[i]);
if (i>=2) join(a[i-1],a[i]);
}
}
for (int i=1;i<=n;i++){
int sb = find1(i);
a[i] = sb;///节省空间,继续用a[i]储存首领是谁
cnt[sb]++;
}
//for (int i =1;i<=n;i++) printf("cnt[%d]=%d\n",i,cnt[i]);
for (int i=1;i<=n;i++)
if (i==1) printf("%d",cnt[a[i]]);
else printf(" %d",cnt[a[i]]);
printf("\n");
return 0;
}
Problem D
栈来模拟整个染色过程。
当前的最大深度 = 未被右括号拼在一起的左括号的数量。
左括号的放入遵循使得当前深度小,
右括号的放入也遵循这个规则。
所以这应该是贪心算法。
感觉很多字符串相关的题目都可以这么贪出来。
比方说这题,不过这题我没理解。
https://ac.nowcoder.com/acm/contest/551/D
代码:
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<stack>
#define debug(x) printf("----Line %s----\n",#x)
#define ll long long
#define inf 0x3f3f3f3f
using namespace std;
const int N = 2e5+5;
char ss[N];
bool vis[N];
stack<int>r,s;
int nowl_r=0,nowl_s=0;
int main()
{
int n;
scanf("%d",&n);
scanf("%s",ss);
r.push(0);
nowl_r++;
for (int i=1;i<n;i++){
if (ss[i]=='('){
if (nowl_r < nowl_s) r.push(i),nowl_r++/*,debug("左括号塞到r")*/;
else s.push(i),nowl_s++/*,debug("左括号塞到s")*/;
}
else {
if (nowl_r > nowl_s) r.push(i),nowl_r--/*,debug("右括号塞到r")*/;
else s.push(i),nowl_s--/*,debug("右括号塞到s")*/;
}
}
while (!r.empty()){vis[r.top()] = true;r.pop();}
for (int i=0;i<n;i++)
if (vis[i]) printf("1");
else printf("0");
printf("\n");
return 0;
}