Codeforces Round #644 (Div. 3)

58 篇文章 0 订阅
13 篇文章 1 订阅

A. Minimal Square

题意:两个相等的矩形,长宽为a,b求一个最小的正方形,能够不重叠地放下这两个矩形。

思路:要么都横着放,要么都竖着放,要么一横一竖。取最小。

AC代码:

#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define PII pair<int,int>
const int N = 1e6+10;
const int mod = 1e9+7;
using namespace std;
int n,m;
int res =0 ;
int k,q;
int cnt[N];
int a[N];
int b[N];
int mark[N];
int mark2[N];
 
signed main(){
    int t = 1;
    cin>>t;
    while(t--){
        int a,b;
        cin>>a>>b;
        int res = a+b;
        res = min(res,max(2*a,b));
        res = min(res,max(a,2*b));
        cout<<res*res<<endl;
    }
    return 0;
}

B. Honest Coach

题意:给定一个数组,分成两部分,且不为空,求 第一部分的最大值和第二部分的最小值的差值 的最小值。

思路:显然,排个序之后,求相邻两数的最小差值,就是解。

AC代码:

#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define PII pair<int,int>
const int N = 1e6+10;
const int mod = 1e9+7;
using namespace std;
int n,m;
int res =0 ;
int k,q;
int cnt[N];
int a[N];
int b[N];
int mark[N];
int mark2[N];
 
signed main(){
    int t = 1;
    cin>>t;
    while(t--){
        cin>>n;
        for(int i = 0 ; i < n ; i ++) cin>>a[i];
        sort(a,a+n);
        int res = a[n-1]-a[0];
        for(int i = 1 ; i < n ; i ++){
            res = min(a[i]-a[i-1],res);
        }
        cout<<res<<endl;
    }
    return 0;
}

C. Similar Pairs

题意:给定一个数组,定义 奇偶性相同的 或者 绝对值相差1 的数为同类的数。问能否把n个数分成n/2组同类的数。

思路:显然,求出奇偶的个数,对于定义的第二种情况,如果选了两个数,那么奇偶个数各减1。因为n是偶数,当奇数个数为偶数时,偶数个数也是偶数,反之同理。那么只有当奇数个数为奇数时,只要用定义2拿走一组数,就都变成偶数了。那就可以两两分组了!

AC代码:

#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define PII pair<int,int>
const int N = 1e6+10;
const int mod = 1e9+7;
using namespace std;
int n,m;
int res =0 ;
int k,q;
int cnt[N];
int a[N];
int b[N];
int mark[N];
int mark2[N];
 
signed main(){
    int t = 1;
    cin>>t;
    while(t--){
        cin>>n;
        for(int i = 0 ; i < n ; i ++) cin>>a[i];
        sort(a,a+n);
        int cnt = 0;
        for(int i = 0 ; i < n ; i ++) cnt += a[i]%2;
        int cnt2 = 0;
        int cnt1 = n-cnt;
        for(int i = 1 ; i < n ; i ++){
            if(a[i]-a[i-1] == 1){
                    cnt2++; i ++;
            }
        }
        if(cnt%2 == 0 || cnt2 >0){
            cout<<"YES"<<endl;
        }else{
            cout<<"NO"<<endl;
        }
    }
    return 0;
}

D. Buying Shovels

题意:去商店买东西,总共要买n件(不能多不能少),但是商店只能一捆一捆得卖(捆绑销售)。每一捆分别装有 1-k 件商品。现在只能选某一捆买,每个不同的捆 数量是无限多的。问最少需要买几捆。

思路:显然,是要找不大于k的,最大的n的约数x。答案就是 n/x。

AC代码:

#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define PII pair<int,int>
const int N = 1e6+10;
const int mod = 1e9+7;
using namespace std;
int n,m;
int res =0 ;
int k,q;
int cnt[N];
int a[N];
int b[N];
int mark[N];
int mark2[N];
 
signed main(){
    int t = 1;
    cin>>t;
    while(t--){
        int x,y;
        cin>>x>>y;
        if(y >= x){
            cout<<1<<endl;
        }else{
            int res = x;
            for(int i = 1 ; i*i <= x  && i <= y; i ++){
                if(x%i == 0){
                    res = min(res,x/i);
                    if(x/i <= y)
                        res = min(res,x/(x/i));
                }
            }
            cout<<res<<endl;
        }
 
    }
    return 0;
}

E. Polygon

题意:这样的子的炮阵,每个炮可以向前开炮,炮弹会在碰到墙时或者碰到别的炮时停下来,并停留在那里。现在给出一个01矩阵,1表示炮弹,问是否是能通过合理的开炮顺序,形成这样的矩阵。

在这里插入图片描述
在这里插入图片描述

思路:显然,左边的炮发射出去会一路向东(右),上面的炮发射出去会一路向南(下),直到碰到障碍物。那么显然,每一个停下来的炮弹,要么被右边挡住了去路,要么被下边挡住了去路,如果一个炮弹两边都没挡住却停留在了那里,那就是不合法的。只需要判断这个就行。

AC代码:

#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define PII pair<int,int>
const int N = 1e6+10;
const int mod = 1e9+7;
using namespace std;
int n,m;
int res =0 ;
int k,q;
int cnt[N];
int a[N];
int b[N];
int mark[N];
int mark2[N];
string s[1005];
signed main(){
    int t = 1;
    cin>>t;
    while(t--){
        cin>>n;
        for(int i = 0 ; i < n ; i ++) cin>>s[i];
        int flag = 1;
        for(int i = 0 ; i < n ; i ++){
            for(int j = 0 ; j <n ; j  ++){
                if(s[i][j] == '1'){
                    if((i+1 >= n || s[i+1][j] == '1') || (j+1 >= n || s[i][j+1] == '1')){
 
                    }else{
                        flag = 0;
                        break;
                    }
                }
 
            }
            if(!flag) break;
        }
        puts(flag ? "YES" : "NO");
 
    }
    return 0;
}

F. Spy-string

题意:给定n个长度为m的字符串,让找出一个字符串使得和任意一个字符串只有最多一个不同的字符。没有则输出-1

思路:刚开始想了一会,有没有啥规律,想了半天没想出来,作罢。写了一手暴力dfs。适当的剪枝一下就行了。

AC代码:

#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define PII pair<int,int>
const int N = 1e6+10;
const int mod = 1e9+7;
using namespace std;
int n,m;
int res =0 ;
int k,q;
int cnt[N];
int a[N];
int b[N];
int mark[N];
int mark2[N];
string s[1005];
char ans[10005];
int flag;
 
bool check(int pos){
    for(int i = 0 ; i < n ; i ++){
        int cnt = 0;
        for(int j = 0 ; j <= pos ; j ++){
            if(s[i][j] != ans[j]) cnt++;
            if(cnt > 1) return false;
        }
    }
    return true;
}
 
void dfs(int pos){
    if(flag) return;
    if(pos == m){
        flag = 1;
        return;
    }
    for(int i = 0 ; i < 26 ; i ++){
        ans[pos] = ('a'+i);
        if(check(pos)){
            dfs(pos+1);
        }
        if(flag) return;
    }
}
signed main(){
    int t = 1;
    cin>>t;
    while(t--){
        cin>>n>>m;
        for(int i = 0 ; i < n ; i ++) cin>>s[i];
        flag = 0;
        dfs(0);
        if(flag){
            for(int i = 0 ; i < m ; i ++){
                cout<<ans[i];
            }
            cout<<endl;
        }else{
            cout<<-1<<endl;
        }
    }
    return 0;
}

G. A/B Matrix

题意:问能不能找到一种每行有a个1,每列有b个1,的大小为n*m的矩阵。

思路:首先判断不合法的条件,合法的条件就是n*b == m*a,至少要保证1的个数一致嘛,不然不就相互矛盾了。然后开始填矩阵,就从(0,0)位置开始按行填连续的1,第一行填a个1,第二行就不要从头开始填,从上次结束的位置的下一个位置,开始填。这样的做的目的呢,就相等于,用n*a个1 去均匀得覆盖 m列,那么显然每一列上就会有 (n*a)/m个1,因为n*b == m*a 所以正好是满足条件的。

AC代码:

#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define PII pair<int,int>
const int N = 1e6+10;
const int mod = 1e9+7;
using namespace std;
int n,m;
int k,q;
int a,b;
int res[100][100];
void show(){
    for(int i = 0 ; i < n ; i ++){
        for(int j = 0 ; j < m ; j ++){
            cout<<res[i][j];
        }
        cout<<endl;
    }
}
 
signed main(){
    int t = 1;
    cin>>t;
    while(t--){
        cin>>n>>m>>a>>b;
        if(b*m != a*n){
            cout<<"NO"<<endl;
        }else{
            cout<<"YES"<<endl;
            int flag = 0;
            int pre = 0;
            for(int i = 0 ; i < n ; i ++){
                int tmp = 0;
                int tt = 0;
                for(int j = 0 ; j < m ; j ++){
                    if(tmp < a){
                        res[i][pre] = 1;
                        pre = (pre+1)%m;
                        tmp ++;
                    }else{
                        res[i][(pre+tt++)%m] = 0;
                    }
                }
            }
            show();
        }
    }
    return 0;
}

H. Binary Median

题意:给出n个二进制数和一个m。表示从[0,2m-1] 中删除这些数。然后求剩下的中位数。

思路:如果没有删除数,那么答案显然是 mid = (2m-1)/2,现在假设删除都是mid 右边的数。也就是 mid = (2m-n-1)/2。但是显然假设不成立。可能也会删mid左边的数。所以如果a[i] < mid,mid就要往右移动一格,也就是 mid += 1 。所以对a排个序就好了。

AC代码:

#include <iostream>
#include <bits/stdc++.h>
#define int long long
#define mk make_pair
#define gcd __gcd
using namespace std;
const double eps = 1e-10;
const int mod = 1e9+7;
const int N = 3e3+7;
int n,m,k,t = 1,cas = 1;
int a[N],b[N];

signed main(){
    cin>>t;
    while(t--){
        cin>>n>>m;
        for(int i = 0 ; i < n ; i ++){
            string s;cin>>s;
            a[i] = 0;
            for(int j = 0 ; j < m ; j ++){
                a[i] = (a[i]<<1)+s[j]-'0';
            }
        }
        sort(a,a+n);
        int mid = ((1LL<<m)-n-1)>>1;
        for(int i = 0; i < n ; i ++){
            if(a[i] <= mid) mid ++;
        }
        char s[200];
        for(int i = 0 ; i < m ; i ++){
            s[i] = '0'+(mid&1);
            mid >>= 1;
        }
        for(int i = m-1 ; i >= 0 ; i --){
            cout<<s[i];
        }
        cout<<endl;
    }
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值