Codeforces Round #654 (Div. 2) - 划水

Codeforces Round #654 (Div. 2)

https://codeforces.com/contest/1371

A. Magical Sticks

题解

题意为给出1、2、3……、n这样一个序列,通过选出两个数a、b,将a+b加入序列中并删除a和b,求出可以得到的最大的相同数个数。
因为1+(n-1)=2+(n-2)=……=(n-1)/2+(n+1)/2=n,
当n为奇数时,正好有(n-1)/2个,当n为偶数时,因为(n-1)/2=(n+1)/2,所以只有n/2-1个。

Code

#include<bits/stdc++.h>
#define IO  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std; 
 
const int inf=0x3f3f3f3f;
typedef long long ll; 
const int N=5007;
const ll mod=998244353;       

int main(){ 
    IO;
    int t=1;
    cin>>t;
    while(t--){  
        int n,m;
        cin>>n;
        cout<<(n+1)/2<<endl;
    }
    return 0;
}

B. Magical Calendar

题解

当n=1时只有1种情况。
当n!=1时考虑n和k的关系:

  • n>k,此时有k种情况,在第几行是等价的所以只考虑列,起点位置可以从第1列取到第k列。
  • n<=k,此时不能将连续的n天分割在两行(类似于例子中给出的),其他情况都是1种情况。

因为1=<k<=r,判断n与r的关系:

  • n>r,此时k无论如何取值都满足n>k,则答案为:\(\sum_1^r\)k,即(1+r)*r/2;
  • n>=r,此时当k取值为k<n时,仍满足n>k,当k>=n时,答案为1,相加即可:\(\sum_1^m\)k+1,m=n-1,即(n-1)*n/2+1;

Code

#include<bits/stdc++.h>
#define IO  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std; 
 
const int inf=0x3f3f3f3f;
typedef long long ll; 
const int N=5007;
const ll mod=998244353;       

int main(){ 
    IO;
    int t=1;
    cin>>t;
    while(t--){  
        ll n,r;
        cin>>n>>r;
        if(n==1){
            cout<<1<<endl;
            continue;
        }
        if(n>r){
            cout<<(1+r)*r/2<<endl;
        }
        else if(n==r){
            cout<<(r-1)*r/2+1<<endl;
        }
        else{
            cout<<(n-1)*n/2+1<<endl;
        }
    }
    return 0;
}

题解

题意为有两类客人,两种食物,当其中一种食物数量严格大于另一种时,第一类客人会吃多的食物,第二类会吃少的,否则可以随便吃,一次吃一个。询问给出的条件是否可以满足所有客人。

首先如果食物数量小于客人数量则不可能满足。
考虑最优情况应该是两类食物数量一样时,此时第一类和第二类客人可以轮流吃。
所以首先用第一类客人将两类食物尽量处理成数量相同的情况,处理后

  • 如果两类食物数量相同,
    若第一类客人数量大于等于第二类客人一定可以满足题意(第一类客人在任何情况下都可以吃食物);
    若第二类客人数量多,并且数量大于任一食物数量则无法满足客人,否则可以满足。
  • 如果两类食物不相等
    此时第一类客人数量为0,并且第二类客人只能吃一类食物,判断食物数量和客人数量即可。

Code

#include<bits/stdc++.h>
#define IO  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std; 
 
const int inf=0x3f3f3f3f;
typedef long long ll; 
const int N=5007;
const ll mod=998244353;       

int main(){ 
    IO;
    int t=1;
    cin>>t;
    while(t--){  
        ll a,b,n,m;
        cin>>a>>b>>n>>m;
        if(a+b<n+m){
            cout<<"No"<<endl;
            continue;
        } 
        if(a<b)swap(a,b);
        ll k=min(a-b,n);
        n-=k;
        a-=k;
        if(a==b){
            if(n>=m)cout<<"Yes"<<endl;
            else {
                a-=n;
                m-=n;
                if(m>a)cout<<"No"<<endl;
                else cout<<"Yes"<<endl;
            }
        }else{
            if(m>b)cout<<"No"<<endl;
            else cout<<"Yes"<<endl;
        }
    }
    return 0;
}

D. Grid-00100

题解

题意为给出矩阵的维数n,和矩阵元素(为0或1)的和k,求出 每行求和的最大值与最小值差值的平方 与 每列求和的最大值与最小值差值的平方之和 最小的矩阵。
考虑最优情况,当n=k时,此时只需要将主对角线上的元素设为1即可,答案为0.
所以依此类推,当k%n=0时,将每行和设为k/n,总存在将每行和每列和都为k/n的方案,此时答案为0,方案为从主对角线开始向后k/n都置为1;
当k%n!=0时,此时只需要将前k%n多向后置一个位置即可,此时最大值比最小值大1,答案为2。

Code

#include<bits/stdc++.h>
#define IO  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std; 
 
const int inf=0x3f3f3f3f;
typedef long long ll; 
const int N= 1e5+7;
const ll mod=998244353;       

int a[307][307];

int main(){ 
    IO;
    int t=1;
    cin>>t;
    while(t--){  
        int n,k;
        memset(a,0,sizeof(a));
        cin>>n>>k;
        int len=k/n;
        int x=k%n;
        cout<<2*(x>0)<<endl;

        for (int i = 0; i < x; ++i)
        {
            for (int j = i; j <= i+len; ++j)
            {
                a[i][j%n]=1;
            }
        }

        for (int i = x; i < n; ++i)
        {
            for (int j = i; j < i+len; ++j)
            {
                a[i][j%n]=1;
            }
        }
        for (int i = 0; i < n; ++i)
        {
            for (int j = 0; j < n; ++j)
            {
                cout<<a[i][j];
            }cout<<endl;
        }
    }
    return 0;
}

E1. Asterism (Easy Version)

思路

题意为Aoi开始有x个糖果,他有n个敌人,每i个敌人有ai个糖果,你可以通过变换敌人的次序来和Aoi进行比较糖果,如果Aoi的糖果大于等于敌人,则Aoi胜出并获得一个糖果,对于每个x的情况如果获胜的情况数不被p整除则认为是一个好的数字,输出所有的好数字。

分析x的范围,因为ai可以随意排列则从小到大排序后结果最优,x最小的情况是经过n-1轮后正好等于最大的敌人的糖果数,即x>=max(a)-(n-1),最大情况是max(a)-1,如果x>=max(a),则所有情况(n!)都可以使Aoi每轮获胜,因为n>=p,所以n!%p=0一定成立,故此时x不满足题意,所以x最大值为max(a)-1。

暴力搜x的区间找出答案即可。
判断x是否为好数时,枚举每个位置的取值情况,相乘对p取模判断最后是否为0即可。

Code

#include<bits/stdc++.h>
#define IO  ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std; 
 
const int inf=0x3f3f3f3f;
typedef long long ll; 
const int N= 1e5+7;
const ll mod=998244353;       

int a[N];

int main(){ 
    IO;
    int t=1;
    //cin>>t;
    while(t--){  
        int n,p;
        cin>>n>>p;
        map<int,int>mp;
        for (int i = 0; i < n; ++i)
        {
            cin>>a[i];
            mp[a[i]]++;
        }sort(a,a+n);
        vector<int>ans;
        for (int i = max(a[n-1]-n+1,1); i < a[n-1]; ++i)
        {
            int sum=0,cnt=1;
            for (int j = 0; j < n; ++j)
            {
                if(a[j]<i)sum++;
                else break;
            }
            for (int j = i; j <= i+n-1; ++j)
            {
                sum+=mp[j];
                cnt=cnt*sum%p;
                sum--;
            }if(cnt){
                ans.push_back(i);
            }
        }cout<<ans.size()<<endl;
        for(int i:ans)cout<<i<<" ";
        cout<<endl;
    }
    return 0;
}
posted @ 2021-01-31 21:41  !^^!  阅读(92)  评论(0)    收藏  举报