A. Card Game
看最大值是否在the first player 的牌里面。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t,n,k1,k2;
scanf("%d",&t);
while(t--)
{
scanf("%d%d%d",&n,&k1,&k2);
int f=1,maxn=0;
int x;
for(int i=1;i<=k1;i++)
{
scanf("%d",&x);
if(x>maxn)
maxn=x;
}
for(int i=1;i<=k2;i++)
{
scanf("%d",&x);
if(x>maxn)
{
maxn=x;
f=2;
}
}
if(f==1)
printf("YES\n");
else
printf("NO\n");
}
return 0;
}
B. Interesting Subarray
这个题目,最开始的反应是确定相隔最近的最大值和最小值位置,通过这个来判断是否可以。但由于有重复的元素,要找到相隔最近的最大值和最小值的位置,复杂度太高。后来冷静下来发现,其实没必要。对于一个满足要求的序列,如果满足max-min>=k,那么该数组中必然有相邻的两个数其差值大于2。那么只要把原数组扫一遍,判断一下即可。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t,n,a,b;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
scanf("%d",&a);
int f=0;
for(int i=2;i<=n;i++)
{
scanf("%d",&b);
if(f==0&&abs(a-b)>=2)
{
printf("YES\n");
printf("%d %d\n",i-1,i);
f=1;
}
a=b;
}
if(!f)
printf("NO\n");
}
}
C. Make Good
想了很久,实在没有思路。
假设数的和为sum,异或和为x.
Solution1:
首先我们先考虑一种情况:当sum<=2x,并且sum为偶数时,那么我们可以加上两个相同的数(2x-sum)/2,那么sum的值就可以变成2x,而x的值不变。
那么其他的情况能否转换为这种情况呢?
我们可以取一个大数res=(1LL<<50)+(sum%2),那么res+sum的值一定是一个大于(1<<50),并且小于 (1<<51)的一个偶数,而x ^ res,一定是一个大于等于(1<<50)的数,所以2x大于等于(1<<51)。
即sum<=2x,那么就转化为上述的情形。
**主要还是会根据数据估计取值的范围,学会利用异或的知识。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll sum,x;
int main()
{
int t,n,a;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
sum=0,x=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
sum+=a;
x^=a;
}
ll res=(1LL<<50)+(sum%2);
sum+=res;
x^=res;
ll t=2*x-sum;
printf("3\n");
printf("%lld %lld %lld\n",res,t/2,t/2);
}
return 0;
}
Solution2:
直接求出这两个数,一个数为x,一个为sum。
因为sum+x+x+sum=2*(x+sum)=2*(x^ x ^(x+sum))。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int t,n,a;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
long long sum=0,x=0;
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
sum+=a;
x^=a;
}
printf("2\n");
printf("%lld %lld\n",x+sum,x);
}
return 0;
}
D. Strange Device
以前没有做过这种类型的题目。相当于是和系统交互。
用k+1次询问即可解决。
对于一个长度为k的序列而言,其中第m大的数是bm,第m+1大的数是bm+1,如果除去一个的一个数是小于等于bm的,那么查询的第m大的数就是bm+1,如果是大于bm的,那么查询的第m大的数是bm。所以依次把1~k+1个数除去,那么查询结果中,bm+1出现的次数为m,bm出现的次数为k+1-m,所以m的值即为最大值出现的次数。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,k,pos,num;
while(scanf("%d%d",&n,&k)!=EOF)
{
int cnt=0;
int a[505]={0};
for(int i=1;i<=k+1;i++)
{
cout<<"?";
for(int j=1;j<=k+1;j++)
{
if(i!=j)
cout<<" "<<j;
}
cout<<endl;
cout.flush();//Idleness limit exceeded
cin>>pos>>num;
a[++cnt]=num;
}
int maxn=a[1],m=0;
for(int i=1;i<=cnt;i++)
{
if(a[i]>maxn)
maxn=a[i];
}
for(int i=1;i<=cnt;i++)
{
if(a[i]==maxn)
m++;
}
cout<<"! "<<m<<endl;
cout.flush();//Idleness limit exceeded
}
return 0;
}
持续更新中。。。