A Boboniu Likes to Color Balls
分情况讨论一下即可。全为偶数,或者三个为偶数,是肯定可以的。只有两个为偶数是肯定不可以的。有一个为偶数,或者没有一个是偶数的情况,得看是否红,蓝,绿气球都有,如果都有则可以(可以转化成成立的情况),否则不可以。
#include
#include
using namespace std;
int T,r,g,b,w;
int main()
{
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d",&r,&g,&b,&w);
if(r%2==0&&g%2==0&&b%2==0&&w%2==0)
{
puts("Yes");
continue;
}
int res=0;
if(r%2==1)
res++;
if(g%2==1)
res++;
if(b%2==1)
res++;
if(w%2==1)
res++;
if(((res==3||res==4)&&r&&g&&b)||(!res)||(res==1))
{
puts("Yes");
continue;
}
else
{
puts("No");
continue;
}
}
return 0;
}
B Boboniu Plays Chess
直接按规则,先跑行,再跳到其它列再跑,或者先跑列,再跳到其他行再跑,皆可以。
#include
#include
#include
#include
using namespace std;
int n,m,Sx,Sy;
int main()
{
scanf("%d%d%d%d",&n,&m,&Sx,&Sy);
printf("%d %d\n",Sx,Sy);
for(int i=m;i>=1;i--)
{
if(i!=Sy)
printf("%d %d\n",Sx,i);
}
int flag=1;
for(int i=1;i<=n;++i)
{
if(i!=Sx)
{
if(flag)
{
for(int j=1;j<=m;++j)
printf("%d %d\n",i,j);
}
else
{
for(int j=m;j>=1;j--)
printf("%d %d\n",i,j);
}
flag^=1;
}
}
return 0;
}
C Boboniu and Bit Operations
并不是直接取与的最小值或上就可以,因为如果对于任意的j,ai&bj在某一位上都是1,说明这位必是1,那么再选最小值的不用考虑这一位。所以,我们枚举9位,如果存在1个i对于任意的j,ai&bj在那位都是1,那么那位必取1,否则取0,然后将取1的标记掉,下次不再找它。
#include
#include
#include
#include
using namespace std;
const int maxn=210;
const int inf=0x3f3f3f3f;
int n,m,ans;
int a[maxn],b[maxn],num[25];
int c[maxn][maxn][10];
int limit[maxn];
bool vis[maxn][maxn];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
for(int j=1;j<=m;++j)
scanf("%d",&b[j]);
num[0]=1;
for(int i=1;i<=9;++i)
num[i]=num[i-1]*2;
for(int i=1;i<=n;++i)
{
limit[i]=m;
for(int j=1;j<=m;++j)
{
int tmp=a[i]&b[j];
int tot=0;
while(tmp)
{
c[i][j][tot++]=tmp%2;
tmp>>=1;
}
}
}
for(int k=8;k>=0;k--)
{
bool flag=0;
for(int i=1;i<=n;++i)
{
int len=0;
for(int j=1;j<=m;++j)
{
if(c[i][j][k]&&!vis[i][j])
len++;
}
if(len==limit[i])
{
flag=1;
ans+=num[k];
break;
}
}
if(!flag)
{
for(int i=1;i<=n;++i)
for(int j=1;j<=m;++j)
if(c[i][j][k]&&!vis[i][j])
{
vis[i][j]=1;
limit[i]--;
}
}
}
printf("%d\n",ans);
return 0;
}
D Boboniu Chats with Du
将a[]分成,>m和<=m的两部分,然后>m从大到小排序,<=m从小到大排序,分别求前缀和,然后枚举选>m的数量,利用前缀和,O(1)算出此时最大值更新答案。(注意会爆int)
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn=1e5+5;
int n,d,m,x;
int a[maxn],b[maxn];
ll sum1[maxn],sum2[maxn];
int tot1,tot2;
int main()
{
scanf("%d%d%d",&n,&d,&m);
for(int i=1;i<=n;++i)
{
scanf("%d",&x);
if(x<=m)
a[++tot1]=x;
else
b[++tot2]=x;
}
sort(a+1,a+1+tot1);
sort(b+1,b+1+tot2,greater<int>());
for(int i=1;i<=tot1;++i)
sum1[i]=sum1[i-1]+a[i];
for(int j=1;j<=tot2;++j)
sum2[j]=sum2[j-1]+b[j];
if(!tot2)
{
printf("%lld\n",sum1[tot1]-sum1[0]);
return 0;
}
ll ans=0;
for(int i=1;i<=tot2;++i)
{
if(i+1ll*i*d<1ll*tot2)
continue;
if(i+1ll*(i-1)*d>1ll*n)
continue;
ans=max(ans,sum2[i]-sum2[0]+sum1[tot1]-sum1[min(1ll*tot1,max(0ll,1ll*(i-1)*d-(tot2-i)))]);
}
printf("%lld\n",ans);
return 0;
}