HZNU 2019 Summer Selection conte
地址:https://cn.vjudge.net/contest/308823#overview
目录:
A: CodeForces 1136D
B: CodeForces 1152B
C: CodeForces 1061D
D: CodeForces 1169B
E: CodeForces 1169C
F: CodeForces 1169D
G: CodeForces 813C
H: CodeForces 675C
I: CodeForces 862A
J: CodeForces 842D
B - Neko Performs Cat Furrier Transform
题目链接:https://cn.vjudge.net/contest/308823#problem/B
参考(dalao)的博客:
https://www.cnblogs.com/LMCC1108/p/10768353.html
https://www.cnblogs.com/--ChenShou--/p/10778678.html
题意:
将数字经过一系列的处理 (轮流进行加法操作和异或操作且加数和异或数有要求,加法只能加一,异或只能对2的n次方-1异或)( + ^ + ^ + ^ + ^ ......) 后变成——在二进制表示下从最高位到最低位都是1
题目思路:从最高位开始把0变成1(因为对更小的数进行异或操作只会对低位影响而不会对高位有影响)
AC代码(我的代码只是大佬的代码的另一种方式。。。。侵删)
#include<vector>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<map>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=300050;
map<int,int>m;
vector<int> b;
int main(){
int a;
m[0]=1;
int end=1;//中止情况
for(int i=1;i<=30;i++)
{
end<<=1;
m[end-1]=1;
}
scanf("%d",&a);//
int count=0;
while(!m[a])
{
count++;
if(count&1)
{
int y=a&(-a),n=0;
a^=(y-1);
while(y){
n++;
y>>=1;
}
b.push_back(n-1);
}
else a++;
}
printf("%d\n",count);
for(int i=0;i<b.size();i++){
if(i) printf(" ");
printf("%d",b[i]);
}
printf("\n");
return 0;
}
D - Pairs
题目地址:https://cn.vjudge.net/contest/308823#problem/D
参考博客:
https://www.cnblogs.com/YDDDD/p/10930203.html
https://blog.csdn.net/IS_project/article/details/90610098
思路:通过枚举第一个数对中的数字可以确定后面的数字。即如果a1=x,那么把所有不含a1的数对存起来,判断数对中数字最多的数量是否=不含a1的数的总个数,同理可以枚举b1=x。
AC代码:
#include<vector>
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
int x[300005],y[300005],in[300005],in2[300005];
vector<int>g;
int main(){
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++){
scanf("%d%d",&x[i],&y[i]);
}
for(int i=2;i<=m;i++){
if(x[i]!=x[1]&&y[i]!=x[1]){
g.push_back(i);
}
}
bool f=false;
for(int i=0;i<g.size();i++){
in[x[g[i]]]++;
in[y[g[i]]]++;
if(in[x[g[i]]]==g.size()||in[y[g[i]]]==g.size()){
f=true;
}
}
if(g.size()==0)f=true;
g.clear();
for(int i=2;i<=m;i++){
if(x[i]!=y[1]&&y[i]!=y[1]){
g.push_back(i);
}
}
for(int i=0;i<g.size();i++){
in2[x[g[i]]]++;
in2[y[g[i]]]++;
if(in2[x[g[i]]]==g.size()||in2[y[g[i]]]==g.size()){
f=true;
}
}
if(g.size()==0)f=true;
if(f)printf("YES\n");
else printf("NO\n");
return 0;
}
F - Good Triple
参考博客:
https://blog.csdn.net/weixin_38772011/article/details/90605482
https://blog.csdn.net/code92007/article/details/90603458
https://www.cnblogs.com/letlifestop/p/10937664.html
思路:每一次是记录当前这个区间 [ l , r ] ,是否有可行解。如果有可行解的话,这一段对答案的贡献就是右端点到len的距离。(手写了几个样例,发现长度超过9的时候,就基本一定有满足题目条件的区间,因为都是0 和1 )。
AC代码:
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=300050;
char a[maxn];
int main(){
scanf("%s",a);
ll ans=0;
ll n=strlen(a);
for(int k=0;k<n;k++){
for(int i=k;i<n;i++){
bool flag=false;
for(int j=1;i-2*j>=k;j++){
if(a[i]==a[i-j]&&a[i]==a[i-2*j])
{
ans+=n-i;
flag=true;
break;
}
}
if(flag)break;
}
}
printf("%lld\n",ans);
return 0;
}
I - Mahmoud and Ehab and the MEX
参考博客:
https://blog.csdn.net/ever_glow/article/details/78054604
https://blog.csdn.net/qq_34531807/article/details/78073316
思路:
我们记比x小的数有k个,与x相等的数有t个,则ans=x-k+t 。
AC代码:
#include<vector>
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn=10000;
int main(){
int n,m=0,x,ans=0,k=0;
int a[maxn];
cin>>n>>x;
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
if(x==a[i])m++;
else if(x>a[i])k++;
}
printf("%d\n",x-k+m);
return 0;
}