CF 1451
CF 1451 A
观察易发现除了1之外要把一个数变成1必须要经过2,那么对于偶数我们直接把他变成2,对于奇数可以先变成偶数再变成2。
#include<bits/stdc++.h>
using namespace std;
int solve(int x){
//cout<<"?"<<x<<endl;
int temp1;
if(x==1)return 0;
if(x==2)return 1;
if(x==3)return 2;
if(x%2==0)return 2;
if(x%2==1)return 3;
}
int main()
{
int t;scanf("%d",&t);
while(t--){
int temp;cin>>temp;
cout<<solve(temp)<<endl;
}
return 0;
}
CF 1451 B
易发现一个与sub(L[i],R[i])相等的子序列必定要有一个与其L[i]相等或者R[i]相等的位置,而有了这个位置也必定能够得到一个与其相等的子序列。
那么只需要去找一下最左的1,0和最右的1,0即可。
#include<bits/stdc++.h>
using namespace std;
char a[200];
int main()
{
int t;scanf("%d",&t);
while(t--){
int len,q_num,f_0=-1,f_1=-1,l_0=-1,l_1=-1;scanf("%d%d",&len,&q_num);
scanf("%s",a+1);
for(int i=1;i<=len;i++){
if(a[i]=='1'){
//if(f_0==-1)f_0=i;
if(f_1==-1)f_1=i;
//l_0=i;
l_1=i;
}else{
if(f_0==-1)f_0=i;
//if(f_1==-1)f_1=i;
l_0=i;
//l_1=i;
}
}
//cout<<f_0<<","<<f_1<<":"<<l_0<<","<<l_1<<endl;
for(int i=1;i<=q_num;i++){
bool flag=false;int q_l,q_r;scanf("%d%d",&q_l,&q_r);
if(f_0!=q_l&&f_1!=q_l)flag=true;
if(l_0!=q_r&&l_1!=q_r)flag=true;
if(flag)cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
}
}
CF 1451 C
我们可以先给这两个串排一下序,因为易知位置对于答案来说没有影响,那么接着我们只需要把26个字母的个数对应起来就行了。
那么就可以维护26个数,从小到大处理。
当当前字母的数与目标的数量相等时,那么就不需要处理这个字母的个数了。
当当前字母的数比目标的数量大时,那么就需要把这个字母中的一部分丢给下个字母,让下个字母的数量增加k个。
当当前字母的数比目标的数量小时,说明无法达到目标状态。
当处理完所有字母之后发现有字母剩余时,说明无法达到目标状态。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+7;
char a[maxn],b[maxn];
int numa[30],numb[30];
int main()
{
int t;scanf("%d",&t);
while(t--){
memset(numa,0,sizeof(numa));
memset(numb,0,sizeof(numb));
int n,k;scanf("%d%d",&n,&k);
scanf("%s",a+1);scanf("%s",b+1);
for(int i=1;i<=n;i++){
numa[a[i]-'a']++;
numb[b[i]-'a']++;
}
bool falseflag=false;
char now_pos='a';
while(now_pos<='z'){
if(numa[now_pos-'a']==numb[now_pos-'a']){
now_pos++;
}else if(numa[now_pos-'a']>numb[now_pos-'a']){
if(numa[now_pos-'a']>=k&&now_pos!='z')numa[now_pos-'a']-=k,numa[now_pos-'a'+1]+=k;
else{
falseflag=true;break;
}
}else if(numa[now_pos-'a']<numb[now_pos-'a']){
falseflag=true;break;
}
}
if(falseflag){
cout<<"No"<<endl;
}else{
cout<<"Yes"<<endl;
}
}
//system("pause");
return 0;
}
CF 1451 D
观察得,第二个人想维持位置一直处在y=x这条线上的话,那么一定可以让当前位置在y=x上,那么如果y=x的最大的位置是游戏的一个终点的话,那么第二个人获胜。
那么如果y=x不是游戏的终点的话,那么再走一步一定是游戏的终点,那么第一个人就能够等效的维持最终的位置在这个位置。
即我们先不考虑第一个人走的第一步,接下来第二个人怎么走第一个人就反着走。最终一定能够到达游戏的一个终点。第一个人获胜。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int t;scanf("%d",&t);
while(t--){
long long d,k;scanf("%lld%lld",&d,&k);
long long temp=sqrt(0.5)*(double)d;
long long pos1=(temp/k)*k;
//cout<<temp<<"::"<<pos1<<endl;
//cout<<pos1*pos1+(pos1+1)*(pos1+1)<<"~~~"<<d*d<<endl;
if(pos1*pos1+(pos1+k)*(pos1+k)>d*d){
cout<<"Utkarsh"<<endl;
}else{
cout<<"Ashish"<<endl;
}
}
//system("pause");
return 0;
}
cf 1451 E1&E2
易发现如果限制运算次数的话那么,xor运算是必要的,知道所有a[i] xor a[1]的值得到任意两个数的异或值,并且得到一个值以后我们就能得到所有值。
那么得到的n-1个数有两种情况。
其一有两个相等,那么这两个对应的位置必定相等,我们再经过一次AND或OR运算就能够得到该值,最后得到所有值。
其二所有值都不相等,那么必定会有一个值等于n-1,我们能够利用a[1]和这个xor值等于n-1的a[i]做工具。
通过这两个数AND另外一个数a[j]来获取a[j]的两种1的位置,再通过OR运算将这两种1合并到一起,最终得到这个数,然后得到所有的数。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+7;
int xor1[maxn];
int a[maxn];
map<int ,int > mp;
int main()
{
int n;scanf("%d",&n);
bool flag1=false;int pos1=-1,pos2=-1;
for(int i=2;i<=n;i++){
cout<<"XOR "<<i<<" 1"<<endl;
fflush(stdout);
scanf("%d",&xor1[i]);
if(mp[xor1[i]]==0){
mp[xor1[i]]=i;
}else{
pos1=mp[xor1[i]];
pos2=i;
flag1=true;
}
}
if(flag1){
cout<<"AND "<<pos1<<" "<<pos2<<endl;
fflush(stdout);
scanf("%d",&a[pos1]);a[pos2]=a[pos1];
a[1]=xor1[pos1]^a[pos1];
for(int i=2;i<=n;i++){
a[i]=xor1[i]^a[1];
}
}
else{
int posx=-1,posy=n;
for(int i=2;i<=n;i++){
if(xor1[i]==n-1){
posx=i;break;
}
}
if(posx==n)posy=2;
int tempnum1,tempnum2;
cout<<"AND 1 "<<posy<<endl;
fflush(stdout);
scanf("%d",&tempnum1);
cout<<"AND "<<posx<<" "<<posy<<endl;
fflush(stdout);
scanf("%d",&tempnum2);
a[posy]=tempnum1|tempnum2;
a[1]=xor1[posy]^a[posy];
for(int i=2;i<=n;i++){
if(i==posy)continue;
a[i]=xor1[i]^a[1];
}
}
cout<<"!";
for(int i=1;i<=n;i++){
cout<<" "<<a[i];
}cout<<endl;
return 0;
}
cf 1451 F
博弈题。首先考虑对于一个位置来讲,我们能够将其等效为Nim取石子游戏,通过异或值能够得到最终的结果。
但是这道题中各个位置之间是存在关系的,但是能够发现,同一条角度为45°的线上的位置不会相互影响。把各个45°的线看作一个局面。
然后再去考虑枚举各个情况,发现如果某一个局面的xor值为1,那么先手必定可以通过最后一次操做把下一次的局面变成他能够继续赢得局面,最终他获得胜利。
也就是每个对角线上所有值的异或值如果有等于1的,那么先手必胜,否则先手必败。
#include<bits/stdc++.h>
using namespace std;
int mp[107][107];
int xorline[300];
int main()
{
int t;scanf("%d",&t);
while(t--){
memset(xorline,0,sizeof(xorline));
int n,m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%d",&mp[i][j]);
xorline[i+j]^=mp[i][j];
}
}
bool flag=false;
for(int i=2;i<=n+m;i++){
if(xorline[i]){
flag=true;
break;
}
}
if(flag)cout<<"Ashish"<<endl;
else cout<<"Jeel"<<endl;
}
//system("pause");
return 0;
}

浙公网安备 33010602011771号