A:显然都取长度为1,不仅长度优,而且更容易构造。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e3+7;
/*
int head[M],cnt=1;
void init(){cnt=1,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
int vs[M];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
int n,m,x;
memset(vs,0,sizeof(vs));
int fg=-1;
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>x,vs[x]=1;
for(int i=1;i<=m;i++)
{
cin>>x;
if(vs[x])fg=x;
}
if(fg==-1)cout<<"NO"<<endl;
else {
cout<<"YES"<<endl<<1<<" "<<fg<<endl;
}
}
return 0;
}
B:简单的博弈。堆数为1是无法控制的。
而一点谁先手取到堆数不唯一,他直接可以控制是取完这堆还是取到只剩一个:
以便于他先手到下一堆堆数不为1的石子,直到可以取胜的最后一堆不为1的石子。
所以只要看第一堆不为1的石子距离第一堆石子的堆数即可。(全为1特判下就行)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt=1;
void init(){cnt=1,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
int a[M];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
int nm=0;
for(int i=1;i<=n;i++)
{
if(a[i]==1)nm++;
else break;
}
if(nm==n)
{
if(n&1)cout<<"First"<<endl;
else cout<<"Second"<<endl;
}
else
{
if(nm&1)cout<<"Second"<<endl;
else cout<<"First"<<endl;
}
}
return 0;
}
C2:每个字符可以变两次,显然都先变第一个字符,再变整个即可。
从后往前依次变好每一个字符。
这题的瓶颈在于不能每次都翻转,不然会T。
我们仔细观察发现:若每次i都旋转[1-i]字符,则最终字符的排列为:[……n-2,3,n-1,2,n,1];
然后再记录字符翻转次数即可。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 1e5+7;
/*
int head[M],cnt=1;
void init(){cnt=1,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
char a[M],b[M];
int id[M],id2[M];
void cg(int x)
{
if(a[x]=='1')a[x]='0';
else a[x]='1';
}
int main()
{
int T;
cin>>T;
while(T--)
{
int n;
scanf("%d",&n);
scanf("%s%s",a,b);
for(int i=0;i<n;i++)id[i]=0;
vector<int>p;
int sz=0;
id[0]=0;
for(int i=n-1;i>=0;i-=2)id[i]=++sz;
int t=0;if(id[t])t++;
for(int i=t;i<n;i+=2)id[i]=++sz;
for(int i=1;i<n;i++)id2[i]=id[i-1];id2[0]=id[0];
int nm=0;
for(int i=n-1;i>=0;i--)
{
char tp=a[id[i]-1];
if(nm&1)
{
if(tp=='1')tp='0';
else tp='1';
}
if(tp==b[i])p.pb(0),cg(id[i]-1);
p.pb(i);nm++;
}
printf("%d ",p.size());
for(auto x:p)printf("%d ",x+1);
printf("\n");
}
return 0;
}
D:
仔细观察发现:a数组中最大的数和其后面的数一定是连在一起的,否则不会最大的数放前面。
然后把这些数绑定成长度为x的块。剩下的新的a数组重复这个操作。
最后得到sz个块。这要这些块能拼凑成长度为n的数组。就说明能够造出。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define ls (o<<1)
#define rs (o<<1|1)
#define pb push_back
const double PI= acos(-1.0);
const int M = 4000+7;
/*
int head[M],cnt=1;
void init(){cnt=1,memset(head,0,sizeof(head));}
struct EDGE{int to,nxt,w;}ee[M*2];
void add(int x,int y,int w){ee[++cnt].nxt=head[x],ee[cnt].w=w,ee[cnt].to=y,head[x]=cnt;}
*/
int a[M],b[M];
int dp[M];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
set<int>s;
for(int i=1;i<=2*n;i++)
cin>>a[i],s.insert(i);
int sz=0,nm=0;;
for(int i=2*n;i>=1;i--)
{
int tp=*(--s.end());
if(tp==a[i])
{
nm++;
b[++sz]=nm;
nm=0;
}
else nm++;
s.erase(a[i]);
}
// cout<<":iojkojk "<<endl;
for(int j=0;j<=n;j++)dp[j]=0;
dp[0]=1;
for(int i=1;i<=sz;i++)
{
// cout<<"- "<<i<<" "<<b[i]<<endl;
for(int j=n;j>=b[i];j--)
dp[j]+=dp[j-b[i]];
//cout<<i<<" - "<<j<<" = "<<dp[j]<<endl;;
}
if(dp[n])cout<<"YES"<<endl;
else cout<<"NO"<<endl;
}
return 0;
}