Codeforces Round #664解题报告A~D

A、Boboniu Likes to Color Balls

水题,但是写起来挺麻烦的……

#include
#define ll long long
using namespace std;
const int N=500;
ll a[N];
int main()
{
    int t,n;
    int r,g,b,w;
    cin >> t;
    while(t--)
    {
        int js=0,os=0,a0=0;
        for(int i=0;i<4;i++){
            cin >> a[i];
            if(i!=3){
                if(a[i]%2==0)
                    os++;
                else js++;
            }
            if(i!=3&&a[i]==0)
                a0++;
        }
        if(a0==3||(a0==2&&a[3]%2==0))
            cout << "Yes" <<endl;
        else if(a0!=0){
            if(js>1||(js==1&&a[3]%2==1))
                cout << "No" <<endl;
            else
                cout << "Yes" <<endl;
        }
        else{
            if(os==3||js==3)
                cout << "Yes" <<endl;
            else if((os==2&&a[3]%2==0)||(js==2&&a[3]%2==1))
                cout << "Yes" <<endl;
            else
                cout << "No" <<endl;
        }
    }
    return 0;
}

Boboniu Plays Chess

水题,遍历每一行即可。

#include
#define ll long long
using namespace std;
const int N=500;
int n,m;int x0,y0;
int a[N][N];
void work(int l,int pd){//1是逆序,0是正序
    if(l==n+1)
        return;
    if(l==x0)
        work(l+1,pd);
    else{
         if(pd == 1){
            for(int i=m;i>0;i--)
                cout << l << " " << i <<endl;
            work(l+1,0);
        }else{
            for(int i=1;i<=m;i++)
                cout << l << " " << i <<endl;
            work(l+1,1);
        }
    }
}
int main()
{
    //int t,n;
    cin >> n >> m >> x0 >> y0;
    a[x0][y0] = 1;
    cout << x0 << " " << y0 <<endl;;
    for(int i=1;i<=m;i++){
        if(a[x0][i]==0)
            cout << x0 << " " << i <<endl;
    }
    if(x0!=1)
        work(1,1);
    else
        work(2,1);
    return 0;
}

C、Boboniu and Bit Operations

题意:数组a和b,问1<=a<=n,1<=j<=m,将所有的c[i]=a[i]&b[j]取或的最小值为多少,i每个只取一次,j每个可以取任意次。
思路:当时没想出来怎么做,后来找了题解。
从小到大枚举这个最小值,因为它数据最大为 2 9 2^9 29=512,直接枚举即可。
然后进行判断的时候只需要判断在每个a[i]是否有一个b[j]有存在 a[i]&b[j] = s(s为枚举的这个最小值)即可,如果都有一个 a[i]&b[j] = s,那么n个数的或就是这个s,得出答案。
参考博客

#include
#define ll long long
using namespace std;
const int N=500;
int n,m,a[209],b[209];
bool work(int s)
{
    for(int i=1; i<=n; i++)
    {
        int flag=0;
        for(int j=1; j<=m; j++)
        {
            int temp = (a[i]&b[j]);
            if((temp|s)==s) 
                flag=1;
            if(flag) break;
        }
        if(flag==0) 
            return false;
    }
    return true;
}
int main()
{
    cin >> n >> m;
    for(int i=1; i<=n; i++) 
        cin >> a[i];
    for(int i=1; i<=m; i++) 
    	cin >> b[i];
    for(int i=0; i<(1<<9); i++)
        if(work(i))
        {
            cout << i <<endl;
            return 0;
        }
}

D、Boboniu Chats with Du

题意:给 n 个发言后可以得到的快乐值,你可以按任何顺序在群里发言,如果当天发言得到的快乐值为 k i k_i ki的话,当 k i k_i ki > m 时,你会被禁 d 天的禁言(禁言从第二天开始),n 天后你的快乐值的和最大是多少。
思路:贪心。本质就是在算用了多少个大于m的数,枚举用了多少个大于m的数即可。

#include
#define ll long long
using namespace std;
const int N = 1e5+10;
int a[N];
ll h[N],s[N],cnt1,cnt2;
bool cmp(int x,int y){
 return x > y;
}
int main()
{
 int n,d,m,t;
 cin>>n>>d>>m;
 for(int i=1;i<=n;i++) {
  cin>>t;
  if(t>m) h[++cnt1] = t;
  else s[++cnt2] = t;
 }
 sort(h+1,h+1+cnt1,cmp);
 sort(s+1,s+1+cnt2,cmp);
 for(int i=1;i<=cnt1;i++) 
        h[i] += h[i-1];
 for(int i=1;i<=n;i++) 
        s[i] += s[i-1];
 ll ans = s[cnt2];
 for(int num=1;num<=cnt1;num++){//枚举禁言次数
  ll k = (ll)(num-1)*(d+1)+1;//禁言num次时用多少天
  if(k <= n) 
            ans = max(ans,h[num]+s[n-k]);//禁言当天的快乐值+剩余天数中不被禁言的快乐值
 }
 cout<<ans<<endl;
 return 0;
}

你可能感兴趣的:(CF题目)