Codeforces Round #664 (Div. 2)

写了三个题结果C fst了O.0

A - Boboniu Likes to Color Balls

回文串,最多有球是一个奇数个。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include
#include
#include
using namespace std;
int main()
{
    IO;
    int T;
    cin>>T;
    while(T--)
    {
        int a,b,c,d;
        cin>>a>>b>>c>>d;
        int cnt=(a&1)+(b&1)+(c&1)+(d&1);
        if(cnt==0||cnt==1||cnt==4) cout<<"Yes"<<endl;//如果全是4个奇数可以用rgb换一个w,那么就变成全是偶数个
        else if(cnt==2) cout<<"No"<<endl;
        else
        {
        	if(a*b*c) cout<<"Yes"<<endl;
        	else cout<<"No"<<endl;//说明rgb中有球的个数是0 不能换球
        }
    }
    return 0;
}

B - Boboniu Plays Chess

直接模拟,一行一行走,先走完最初所在的行,然后从第一行开始S型走

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include
#include
#include
using namespace std;
const int N=210;
int n,m;
int u,v;
bool st[N];
int main()
{
    IO;
    cin>>n>>m;
    cin>>u>>v;
    cout<<u<<" "<<v<<endl;
    st[u]=1;
    for(int i=1;i<=m;i++)
        if(i!=v) cout<<u<<" "<<i<<endl;
    int v=m;
    for(int i=1;i<=n;i++)
    {
        if(st[i]) continue;
        st[i]=1;
        if(v==m) 
        {
            for(int j=m;j;j--)
                cout<<i<<" "<<j<<endl;
            v=1;
        }
        else
        {
            for(int j=1;j<=m;j++)
                cout<<i<<" "<<j<<endl;
            v=m;
        }
    }
    return 0;
}

C - Boboniu and Bit Operations

贪心的取 c i c_i ci最小最终OR最小不正确。如果某一位必须是1,那么其他 c i c_i ci的该位是否为1就不重要了。
最开始想用trie树实现贪心 c i c_i ci,结果后来一想不正确,就随便写了个dp没想的过了???(结果还是被FST
原因还是上述贪心方法不正确。

FST代码—— O ( n 3 ) O(n^3) O(n3)
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include
#include
#include
#include
using namespace std;
const int N=210;
int a[N],b[N];
int n,m;
int f[N][N];
int main()
{
    IO;
    cin>>n>>m;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=1;i<=m;i++) cin>>b[i];
    memset(f,0x3f,sizeof f);
    for(int i=1;i<=m;i++) f[0][i]=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            for(int k=1;k<=j;k++) f[i][j]=min(f[i][j],f[i-1][j]|(a[i]&b[k]));
    cout<<f[n][m]<<endl;
    
    return 0;
}

正解是枚举答案。我也想过枚举答案可是不知道怎么判断答案是否复合tcl。
如果枚举答案 k k k,那么对于每一个 a i a_i ai都能找一个 b j b_j bj使得a[i]&b[j]二进制中1出现的位置答案中必须也出现,即(a[i]&b[j])|k==k,一一判断即可

正解—— O ( 2 9 n m ) O(2^9nm) O(29nm)
#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include
#include
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N=210;
int a[N],b[N];
int n,m;
int main()
{
    IO;
    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 k=0;k<1<<9;k++)
    {
        
        bool ok1=1;
        for(int i=1;i<=n;i++)
        {
            bool ok2=0;
            for(int j=1;j<=m;j++)
                if(((a[i]&b[j])|k)==k)
                {
                    ok2=1;
                    break;
                }
            if(!ok2)
            {
                ok1=0;
                break;
            }
        }
        if(ok1) return cout<<k<<'\n',0;
    }
}

D - Boboniu Chats with Du

复制数组!!!
分析题目可以简化成如果 a i < = m a_i<=m ai<=m那么代价是 1 1 1,如果 a i > m a_i>m ai>m代价是 d + 1 d+1 d+1很明显是一个01背包,不过数据范围。。。
从集合角度考虑:不妨让小于等于m的放在a[]数组并逆序,大于m放在b[]数组同样逆序,最终的答案一定是a[]数组选出前i个,从b[]数组选出前j个。因此我们可以枚举从b[]数组选择了多少个,然后剩余的从a[]数组选即可。

#define IO ios::sync_with_stdio(false);cin.tie();cout.tie(0)
#include
#include
using namespace std;
typedef pair<int,int> pii;
typedef long long ll;
const int N=100010;
ll a[N],b[N];
int cnta,cntb;
int n,d;
ll m;
int main()
{
    IO;
    cin>>n>>d>>m;
    for(int i=1;i<=n;i++)
    {
        ll x;
        cin>>x;
        if(x>m) b[++cntb]=x;
        else a[++cnta]=x;
    }
    sort(a+1,a+1+cnta);
    sort(b+1,b+1+cntb);
    reverse(a+1,a+1+cnta);
    reverse(b+1,b+1+cntb);
    for(int i=1;i<=cnta;i++) a[i]+=a[i-1];
    for(int i=cnta+1;i<=n;i++) a[i]=a[i-1];//这个地方非常dt 需要赋值一份
    for(int i=1;i<=cntb;i++) b[i]+=b[i-1];
    ll res=0;
    int cntm=min(cntb,(n+d)/(d+1));
    for(int k=0;k<=cntm;k++)
    {//如果不进行上述复制操作 如果n-(d+1)*(k-1)-1>cnt a[n-(d+1)*(k-1)-1]=0 理论应该是所有a[cnta]
        ll now=b[k];
        if(k) now+=a[n-(d+1)*(k-1)-1];//如果不进行上述复制那么now+=a[min(cnta,n-(d+1)*(k-1)-1]
        else now+=a[n];//now+=a[cnta]
        res=max(res,now);
    }
    cout<<res<<endl;
    return 0;
}

emm~~看E群里面讨论的很难 随缘补吧。要加油哦!

你可能感兴趣的:(Codeforces)