Codeforces Round #654 (Div. 2) 【A - E2】

题目链接:https://codeforces.com/contest/1371
集训day1,整个6月都在预习备考,咕了一个多月之后的第一套题。居然只A了3题,然后补了3题。



A - E2 题解

    • A. Magical Sticks
    • B. Magical Calendar
    • C. A Cookie for You
    • D. Grid-00100
    • E2. Asterism (Hard Version)


程序开头,后面不再重复

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define FOR(i,l,r) for(int i=l;i<=r;i++)
#define ROF(i,l,r) for(int i=l;i>=r;i--)
#define pb(x) push_back(x)
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rr(x,y) read(x);read(y)
#define rrr(x,y,z) read(x);read(y);read(z)
#define sss(str) scanf("%s",str+1)
#define ssf(x) scanf("%lf",&x)
#define aLL(x) x.begin(),x.end()
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=2e5+5;
const int M=2e3+5;
const int INF=2e9;
const int sz=15;
const int mod=1e9+7;
const double eps = 1e-8;
const double pi= acos(-1);
template<class T>
inline void read(T &x)
{
    char c;x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}

A. Magical Sticks

这题不难看出,2个拼最划算 ,最大的和最小的拼 ,然后次大的和次小的 …

int n,m;
char str[N];
int f[N];
int main()
{
    int t;
    r(t);
    while(t--){
        r(n);
        int ans=n/2;
        if(n&1) ans++;
        cout<<ans<<endl;
    }
    return 0;
}

B. Magical Calendar

设当前的宽为x,若n>=x 则只有一横条 (即只有一种
在这里插入图片描述
若n等差数列的前n项和
Codeforces Round #654 (Div. 2) 【A - E2】_第1张图片

int main()
{
    int t;
    r(t);
    while(t--){
        rr(n,m);
        LL ans=0;
        if(n<=m){
            ans+=1ll*(n-1)*n/2; //1 - n-1
            ans++;
        }
        else{
            ans+=1ll*(m+1)*m/2;
        }
        cout<<ans<<endl;
    }
    return 0;
}

C. A Cookie for You

这题描述很复杂,也确实把我绕晕了 ,其实说的就是
第一种人:先选多的那种,如果两种相等则选后者
第二种人:先选少的那种,如果两种相等则选前者
现在假设有a 和 b,其中a>b,如果我们先排第二种人,那么b直接就选没了,显然很难满足。所以我们先排第一种人。直到 a = b时,这时选第一种人 那么就是a和b交替减1;选第二种人还是直接选没了。不难发现,不管怎样b都是选少的那方,所以我们不妨先把第二种人排完,然后排第一种人。

int main()
{
    int t;
    r(t);
    while(t--){
        LL a,b,c,d;
        rr(a,b); rr(c,d);
        if(a<b) swap(a,b);
//        if((a==0&&c!=0)||(b==0&&d!=0)){
//            cout<<"NO\n";
//            continue;
//        }
        LL dif=a-b;
        if(c>=dif){
            c-=dif;
            if(b>=d&&2*b>=c+d) cout<<"YES\n";
            else cout<<"NO\n";
        }
        else{
            if(b>=d) cout<<"YES\n";
            else cout<<"NO\n";
        }
    }
    return 0;
}

D. Grid-00100

每次选一条正斜线,就可以保证每次增加的都是均匀的
Codeforces Round #654 (Div. 2) 【A - E2】_第2张图片
比如先选红线为1,再绿线,再蓝线。每一条线经过的点 都是增加不同的行和列,所以均匀
这样不难看出,当选的是整条线时,完全均匀,ans=0,不完整时,最多也只差1,ans=2

int g[500][500];
int main()
{
    int t;
    r(t);
    while(t--){
        rr(n,m);
        memset(g,0,sizeof g);
        int x=1,y=1;
        int tmp=m;
        while(tmp--){
            g[x][y]=1;
            x++; y=y%n+1;
            if(x==n+1){
                x=1;
                y=y%n+1;
            }
        }
        if(m%n==0) cout<<0<<endl;
        else cout<<2<<endl;
        FOR(i,1,n){
            FOR(j,1,n) cout<<g[i][j];
            cout<<endl;
        }
    }
    return 0;
}

E2. Asterism (Hard Version)

这题可以去看题解,我也是看官方题解写出来的https://codeforces.com/blog/entry/79624
首先要明白这个式子
在这里插入图片描述
其中bi表示的是整个序列中小于等于i的数的个数
当我们选第一个数时,肯定是要选小于等于x的数,即bx
第二个数,肯定要小于等于x+1,即bx+1,但是之前选走了一个数,所以只有bx+1 - 1种
以此类推,可得上式

设max为整个序列的最大值
x + n − 1 < m a x x+n-1x+n1<max时,携带的最大的都没有序列的最大值大,肯定不行,即f(x)=0 ,不满足
x ≥ m a x x\geq max xmax时,随便怎么选都可以,即f(x)=n!,也不满足
其他情况就是 m a x − n + 1 ≤ x < m a x max-n+1 \leq xmaxn+1x<max
我们只需要满足
在这里插入图片描述
范围不超过2e5,所以我们可以直接记录i-bi的值,然后直接map找即可

int n,m;
char str[N];
int f[N];
unordered_map<int,int> mm;
int main()
{
    rr(n,m);
    FOR(i,1,n){
        r(f[i]);
    }
    sort(f+1,f+n+1);
    FOR(i,f[n]-n+1,f[n]+n-2){
        mm[i]=(i%m-(upper_bound(f+1,f+n+1,i)-f-1)%m+m)%m;
    }
    unordered_map<int,int> mmm;
    int st=max(0,f[n]-n+1);
    FOR(i,1,n-1){
        int now=st+i-1;
        mmm[mm[now]]++;
    }
    vector<int> ans;
    FOR(i,st,f[n]-1){
        mmm[mm[i+n-1]]++;
        if(mmm.count(i%m)&&mmm[i%m]>0){
//            cout<
        }
        else{
            ans.pb(i);
        }
        mmm[mm[i]]--;
    }
    cout<<ans.size()<<endl;
    for(int x:ans){
        cout<<x<<' ';
    }
    cout<<endl;
    return 0;
}

你可能感兴趣的:(Contests)