Codeforces Round 561(Div 2)题解

这是一场失败的比赛。

前三题应该是随便搞的。

D有点想法,一直死磕D,一直WA。(赛后发现少减了个1……)

看E那么多人过了,猜了个结论交了真过了。

感觉这次升的不光彩……还是等GR3掉了洗掉这次把,,,


A

水题,对于每个首字母分成一半一半即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=100010;
#define MP make_pair
#define PB push_back
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline ll read(){
    char ch=getchar();ll x=0,f=0;
    while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return f?-x:x;
}
int n,cnt[26],ans;
char s[25];
int main(){
    n=read();
    FOR(i,1,n) scanf("%s",s+1),cnt[s[1]-'a']++;
    FOR(i,0,25){
        int x=cnt[i]/2,y=cnt[i]-x;
        ans+=x*(x-1)/2+y*(y-1)/2;
    }
    printf("%d\n",ans);
}
View Code

B

水题。首先行列长度都要 $\ge 5$,然后就可以随便搞了。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=100010;
#define MP make_pair
#define PB push_back
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline ll read(){
    char ch=getchar();ll x=0,f=0;
    while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return f?-x:x;
}
int n,sq,x,y;
int main(){
    n=read();
    for(int i=2;i*i<=n;i++) if(n%i==0) x=i,y=n/i;
    if(x<5 || y<5) return puts("-1"),0;
    FOR(i,1,x){
        if(i%5==1){
            printf("aeiou");
            FOR(j,1,y-5) printf("a");
        }
        if(i%5==2){
            printf("eioua");
            FOR(j,1,y-5) printf("e");
        }
        if(i%5==3){
            printf("iouae");
            FOR(j,1,y-5) printf("i");
        }
        if(i%5==4){
            printf("ouaei");
            FOR(j,1,y-5) printf("o");
        }
        if(i%5==0){
            printf("uaeio");
            FOR(j,1,y-5) printf("u");
        }
    }
}
View Code

C

比较水的一题。

发现把 $a$ 变成 $-a$ 不影响答案($|a-b|$ 变成 $|a+b|$,$|a+b|$ 变成 $|a-b|$)。

那么全变成非负数,枚举较小那个,随便统计一下即可。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=200020;
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline ll read(){
    char ch=getchar();ll x=0,f=0;
    while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return f?-x:x;
}
int n,a[maxn];
ll ans;
inline int binary(int x){return lower_bound(a+1,a+n+1,x)-a;}
int main(){
    n=read();
    FOR(i,1,n) a[i]=abs(read());
    sort(a+1,a+n+1);
    FOR(i,1,n){
        int p=upper_bound(a+1,a+n+1,2*a[i])-a;
        if(p>n) p=n;
        if(a[p]>2*a[i]) p--;
        ans+=p-i;
    }
    cout<<ans;
}
View Code

D

思路上也不是什么难题。但是代码打着真的难受……

枚举答案序列的长度 $k$(先特判 $k=1$ 和 $k=2$ 可不可行,避免一堆讨论)

经过推式子发现 $b=2^{k-2}a+2^{k-3}r_2+2^{k-4}r_3+\dots+2r_{k-2}+r_{k-1}+r_k$。

从前往后考虑 $r_i(2\le i\le k-2)$ 是什么。发现 $r_{i+1}$ 到 $r_n$ 能组成的数最大是 $2^{k-i-1}m$,最小是 $2^{k-i-1}$,而且这之间的数都能被表示出来。

解个方程,$\dfrac{s}{2^{k-i-1}}-m\le x\le \dfrac{s}{2^{k-i-1}}-1$。任取一个合法的数即可。($s$ 是 $b$ 与目前的和的差)

最后 $r_{k-1}+r_k=s$,随便分配一下就行了。

现实很骨感。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline ll read(){
    char ch=getchar();ll x=0,f=0;
    while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return f?-x:x;
}
int q;
ll a,b,m,r[55],p2[55];
int main(){
    p2[0]=1;
    FOR(i,1,50) p2[i]=2*p2[i-1];
    q=read();
    while(q--){
        a=read();b=read();m=read();
        MEM(r,0);
        if(a==b) cout<<1<<" "<<a<<endl;
        else if(b-a<=m) cout<<2<<" "<<a<<" "<<b<<endl;
        else{
            bool flag=false;
            FOR(k,3,50){
                if(p2[k-2]<ceil(1.0*b/(a+m)) || p2[k-2]>b/(a+1)) continue;
                ll s=b-p2[k-2]*a;
                bool ok=true;
                FOR(i,2,k-2){
                    ll upr=1.0*s/p2[k-i-1]-1,lwr=ceil(1.0*s/p2[k-i-1])-m;
                    r[i]=min(upr,m);
                    if(r[i]<lwr){ok=false;break;}
                    s-=p2[k-i-1]*r[i];
                }
                if(!ok) continue;
                r[k-1]=min(m,s-1);
                r[k]=s-r[k-1];
                if(r[k]>m) continue;
                flag=true;
                ll s2=s=a;
                cout<<k<<" "<<s<<" ";
                FOR(i,2,k){
                    s=s2+r[i];
                    cout<<s<<" ";
                    s2+=s;
                }
                cout<<endl;
                break;
            }
            if(!flag) puts("-1");
        }
    }
}
View Code

E

%%%zz猜结论神仙

令第 $i$ 天的限制集合为 $S_i$。

首先发现,如果有两天的集合没有交,那么有 $\operatorname{lcm}{S_i}>\operatorname{lcm}{U-S_i}\ge \operatorname{lcm}{S_j}>\operatorname{lcm}{U-S_j}\ge\operatorname{lcm}{S_i}$,不可能成立。

下面证明如果任意两天集合都有交那么一定有解。

任取 $m$ 个不同的质数 $p_i$。

一开始令 $a_i=1$,接下来如果第 $j$ 天买了第 $i$ 个,那么 $a_i*=p_j$。

那么 $\operatorname{lcm}{S_i}=\prod p_j$。因为 $S_i$ 与其它所有 $S$ 都有交,所以其中的元素一定乘了所有的 $p_i$。

同时 $U-S_i$ 中所有元素都没有乘过 $p_i$,所以 $\operatorname{lcm}{U-S_i}\le\prod_{i\ne j}p_j<\prod p_j=\operatorname{lcm}{S_i}$。

证毕。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
const int maxn=100010;
#define MP make_pair
#define PB push_back
#define lson o<<1,l,mid
#define rson o<<1|1,mid+1,r
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
#define ROF(i,a,b) for(int i=(a);i>=(b);i--)
#define MEM(x,v) memset(x,v,sizeof(x))
inline ll read(){
    char ch=getchar();ll x=0,f=0;
    while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
    return f?-x:x;
}
int m,n,s[55];
bool ss[55][10010];
int main(){
    m=read();n=read();
    FOR(i,1,m){
        s[i]=read();
        FOR(j,1,s[i]) ss[i][read()]=true;
        FOR(j,1,i-1){
            int cnt=0;
            FOR(k,1,n) if(ss[i][k] && ss[j][k]) cnt++;
            if(!cnt) return puts("impossible"),0;
        }
    }
    puts("possible");
}
View Code

 


F

看起来是个大数据结构,以后再来搞吧。

 

posted @ 2019-05-18 09:16  ATS_nantf  阅读(277)  评论(0编辑  收藏  举报