Codeforces Round #644 (Div. 3)A->H(H为进制+reverse)

A:http://codeforces.com/contest/1360/problem/A

题意:

用最小正方形,容下两个相同矩形。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int a,b;
        cin>>a>>b;
        if(a>b)
            swap(a,b);
        if(a*2==b)
            cout<<b*b<<endl;
        else
        {
            if(2*a>b)
                cout<<2*a*2*a<<endl;
            else
                cout<<b*b<<endl;
        }
    }
}

B:http://codeforces.com/contest/1360/problem/B

题意:

将n个数分成两组,要求一组的最大值减去另一组的最小值的绝对值最小。

解析:

直接sort然后找最小间距

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=1e3+10;
int a[56];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        int minn=1e9;
        for(int i=1;i<=n;i++)
            cin>>a[i];
        sort(a+1,a+1+n);
        for(int i=2;i<=n;i++)
            minn=min(minn,a[i]-a[i-1]);
        cout<<minn<<endl;
    }
}

C:http://codeforces.com/contest/1360/problem/C

题意:

给出n个数,要求进行两两配对,配对的两个数满足%2相等或者差值为1。

问是否能把所有数配对成功。

解析:

题中已经表示:n为偶数,所以偶数的数目和奇数的数目的奇偶性是相同的。

如果数目均为偶数,那么所有偶数内部配,奇数内部配,是可以包含所有数的。

如果数目均为奇数,那么遍历一下,是否存在差值为1的两个数,如果有,一定为一奇一偶,数目中把它俩划掉,也是正好可以进行两两配对的。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
int a[80];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        int j=0,o=0,d=0;
        for(int i=1;i<=n;i++)
            {
                cin>>a[i];
                if(a[i]%2!=0)
                    j++;
                else
                    o++;
            }
        sort(a+1,a+1+n);
        for(int i=2;i<=n;i++)
        {
            if(a[i]-1==a[i-1])
            {
                d++;
            }
        }
        if(j%2==0&&o%2==0)
            cout<<"YES"<<endl;
        else
        {
            if(d>0)
                cout<<"YES"<<endl;
            else
                cout<<"NO"<<endl;
        }
    }
}

D:http://codeforces.com/contest/1360/problem/D

题意:

给出n和k,在[1,k]中找到一个x,使得n%x==0而且n/x最小。

解析:

直接遍历的话会超时。既然是找n的因子,那么直接在sqrt(n)以内找就可以了,复杂度为O(sqrt(n))。

通过sqrt(n)左边因子来顺便判断右边

找到的每一个因子,要满足<=k,并不断更新x的最大值,就能保证n/x最小。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
ll minn=1e9;
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        ll n,k;
        cin>>n>>k;
        minn=1e9;
        if(k>=n)
            cout<<"1"<<endl;
        else
        {
            ll maxx=0;
            for(ll i=1;i*i<=n;i++)
            {
                if(n%i==0&&i<=k)
                {
                    if(n/i<=k)
                        maxx=max(maxx,n/i);
                    maxx=max(maxx,i);
                }
            }
            cout<<n/maxx<<endl;
        }
    }
}

E:http://codeforces.com/contest/1360/problem/E

题意:

左边和上面发射炮弹,如果遇到阻碍,那么停住,标为1,而且上一个位置也标为1。给出一个情况,判定是否合法。

解析:

刚开始想复杂了,对于一个1来说,它的下方,要么是边界,要么是1,同理,它的右边也一样。

所以如果一个1的下方和右方满足其中一个条件,就是合法的。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 60;
char mp[maxn][maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n;
        cin>>n;
        for(int i=0;i<n;i++)
            cin>>mp[i];
        int ok = 0;
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++)
            {
                if(i<n-1&&j<n-1&&mp[i][j]=='1')
                {
                    if(mp[i+1][j]!='1'&&mp[i][j+1]!='1')
                        {
                            ok=1;break;
                        }
                }
            }
        if(ok)
            cout<<"NO"<<endl;
        else
            cout<<"YES"<<endl;
    }
}

F:http://codeforces.com/contest/1360/problem/F

题意:

给出n个字符串,是否存在一个串,与这n个字符串最多只有一个位置不相同。

解析:

直接暴力模拟

mp[1~n][1~m]记录每一个字符串。

s[i]记录第一个字符串的每一位。

以第一个字符串为基准,对它修改每一位,并check(),看是否合法:与其他字符串的不同位置数<=1

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn = 60;
char mp[12][12];
char s[12];
int n , m ;
bool check()
{
    for(int i=1;i<n;i++)
    {
        int cnt=0;
        for(int j = 0 ; j  < m ; j++)
        {
            if(mp[i][j]!=s[j])
                cnt++;
        }
        if(cnt>1)
            return false;
    }
    return true;
}
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        cin>>n>>m;
        for(int i=0;i<n;i++)
            cin>>mp[i];
        for(int i=0;i<m;i++)
            s[i]=mp[0][i];
        int ok  = 1;
        for(int i=0;i<m;i++)
        {
            for(char j='a';j<='z';j++)
            {
                s[i]=j;
                if(check())
                {
                    ok=0;
                    break;
                }
            }
            if(!ok)
                {
                //    cout<<s<<"-"<<endl;
                    break;
                }
            s[i]=mp[0][i];        //记得还原!因为每次只能修改一处
        }
//        for(int i=0;i<m;i++)
//            cout<<s[i];
//            cout<<endl;
        s[m]='';
        if(ok)
            cout<<"-1"<<endl;
        else    
            cout<<s<<endl;
    }
}

G:http://codeforces.com/contest/1360/problem/G

题意:

是否存在一个n*m的矩阵,满足每行有a个1,每列有b个1。

解析:

如果一个位置变成了1,那么,它所在的行,列,都要+1。

那么每次同时+1,就变成了n*a==m*b了。满足这个条件,才可以构造。

构造的时候,肯定是尽量平均铺的。

很明显,全扎堆在一起,行满足,列也未必满足。

平均铺的代码:

            int id=0;
            for(int i=0;i<n;i++)
            {
                for(int j=id;j<id+a;j++)
                    mp[i][j%m]=1;//%m防越界
                id+=a;
            }

记得初始化,否则样例都过不了:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
const int maxn=60;
int mp[maxn][maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        int n , m , a , b;
        memset(mp,0,sizeof(mp));//初始化
        cin>>n>>m>>a>>b;
        if(n*a!=m*b)
            cout<<"NO"<<endl;
        else
        {
            int id=0;
            for(int i=0;i<n;i++)
            {
                for(int j=id;j<id+a;j++)
                    mp[i][j%m]=1;
                id+=a;
            }
            cout<<"YES"<<endl;
            for(int i=0;i<n;i++)
            {
                for(int j=0;j<m;j++)
                    cout<<mp[i][j];
                cout<<endl;
            }
        }
    }
}

H:http://codeforces.com/contest/1360/problem/H

题意:

2^m个只含0,1的串,删除掉n个所给串,求排序后处于中位数的那个串。

解析:

01串,其实就是个二进制,所以可以先把它们转化为十进制,也是符合字典序排序的。

总串数为偶数:如果删除的数<中位数,那么中位数的位置要后移;

总串数为奇数:如果删除的数>中位数,那么中位数的位置要前移。

明确了这一点,那么就可以直接进行模拟了。

用vector来储存需要删除的数,用map来标记是否被删除。

逐一删除每一个串,每次求出未删除串中的中位数来。

最后再转化为二进制,倒序输出

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<map>
#include<vector>
using namespace std;
typedef long long ll;
const int maxn=60;
int mp[maxn][maxn];
int main()
{
    int t;
    cin>>t;
    while(t--)
    {
        vector<ll>v;
        ll n , m ;
        cin>>n>>m;
        string s;
        for(int i=1;i<=n;i++)
        {
            cin>>s;
            ll sum=0;
            for(int j=0;j<m;j++)
                sum=sum*2+s[j]-'0';  //从前往后来转十进制
            v.push_back(sum);
        }
        ll all=1ll<<m;  //2^m
        ll md=(all-1)/2;
        map<ll,ll>mp;
        for(int i=0;i<n;i++)
        {
            mp[v[i]]=1;
            if(all%2==0)
            {
                if(v[i]<=md)
                {
                    md++;
                    while(mp[md])  //因为可能md已经被删除了。
                        md++;
                }
            }
            else
            {
                if(v[i]>=md)
                {
                    md--;
                    while(mp[md])
                        md--;
                }
            }
            all--;
        }
    //    cout<<md<<endl;
        string ch;
        for(int i=0;i<m;i++)  //转二进制操作
        {
            if(md>>i&1)
                ch+='1';
            else
                ch+='0';
        }
        reverse(ch.begin(),ch.end());  //倒序操作<algorithm>
        cout<<ch<<endl;
    }
}

 记录一下两个容易混的知识点:

右移 >>

左移 <<

左移几 就是乘以 2的几次方 左移三位 就是 乘以8
右移几 就是除以 2的几次方

原文地址:https://www.cnblogs.com/liyexin/p/12968380.html