ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

# Educational Codeforces Round 135 (Rated for Div. 2) A-E

2022-09-09 22:04:00  阅读:202  来源: 互联网

标签:Educational Rated int ll Codeforces ans print sa rep


Educational Codeforces Round 135 (Rated for Div. 2)

传送门

A

题意:
给定n个颜色的各自的数量,每次可以使用两个不同的颜料,问最后可能剩下哪种颜料,输出任意一个即可。

分析:直接输出个数最多的那个颜料即可

void solve(){
    int n;cin>>n;
    vector<int>a(n+1);
    rep(i,1,n) a[i]=read();
    int pos,maxx=-1;
    rep(i,1,n) 
        if(a[i]>maxx) maxx=a[i],pos=i;
    print(pos);pts;
}  

B

题意:
定义一个长度为\(n\)的排列\(p\)的价值如下:
最初价值为0,
如果\(x<p_1\),则\(x=x+p_1\),否则\(x=0\)
如果\(x<p_2\),则\(x=x+p_2\),否则\(x=0\)
.......
如果\(x<p_n\),则\(x=x+p_n\),否则\(x=0\)

你需要找出一个价值最大的长度为n的排列,任意一个即可。

分析:
对于最后一个位置,\(x<p_n\)才能得到尽可能大的值,而\(x\)最大可取到\(p_n-1\),因此最后一位一定是\(n\),而最后一位前的和为\(n-1\),这样价值最大。

此时不妨让最后两位分别为\(n-1,n\),让前面一直相消即可。对于n为偶数,输出\(2,1,4,3....n-2,n-3,n-1,n\),对于n为奇数,观察到\(1,2,3\)后最后价值为0,因此在输出\(1,2,3\)后同偶数情况即可。

void solve(){
    int n;n=read();
    if(n&1){
        rep(i,1,3) print(i),ptc;
        rep(i,4,n-2){
            print(i+1);ptc;print(i);ptc;
            i++;
        }
        print(n-1);ptc;print(n);pts;
    }
    else{
        rep(i,1,n-2){
            print(i+1);ptc;print(i);ptc;
            i++;
        }
        print(n-1);ptc;print(n);pts;
    }
}  

C

题意:
定义\(f(x)\)为\(x\)在十进制下的位数。
现在给你a,b两个数列,一次操作你可以选择两个数列中的一个数\(y\),将其变为\(f(y)\),你的目的是将两个数列所含的数完全相同,求最少操作数。

分析:
注意到\(a_i,b_i \leq 1e9\),因此一个数最多经过两次变换即可得到\(1\)。之后暴力枚举哪些数变即可。

首先将a,b中已经相同的数去掉,他们不需要再动了。随后对剩下的a,b中的数均进行操作,记录答案,此时已经为1位数的数不用再操作;然后再次筛选已经相同的数,对剩下的数进行操作,记录答案,此时已经为1的数不计入操作。

void solve(){
    int n;n=read();
    multiset<int>a,b,c,d;
    rep(i,1,n){
        int x;x=read();a.insert(x);
    }
    rep(i,1,n){
        int x;x=read();
        if(a.find(x)==a.end() )b.insert(x);
        else a.erase(a.find(x));
    }
    int ans=0;
    for(auto x:a) if(x>9) ans++;
    for(auto x:b) if(x>9) ans++;
    for(auto x:a){
        if(x>9)c.insert(f(x));
        else c.insert(x);
    }
    for(auto x:b){
        int y=x>9? f(x):x;
        if(c.find(y)==c.end()) {
            d.insert(y);
        }
        else c.erase(c.find(y));
    }
    for(auto x:c) if(x!=1) ans++;
    for(auto x:d) if(x!=1) ans++;
    print(ans);pts;
}  

D

题意:
给定一个字符串,Alice和Bob进行游戏,两个人各拥有一个初始为空的字符串,每人每次可以从字符串首或尾取一个字符放入自己字符串的头部,问再字符串取完后是Alice胜还是Bob胜还是平局。

分析:
首先对于取的最终状态是两个字符,此时因为Alice先取,所以终态只有Alice胜和平局,故最后结果也如此。此处直接\(n^2\)记忆化搜索,枚举所有情况,看Alice是否有机会取胜即可。

int n;
char s[maxn];
int mp[maxn][maxn];
int dfs(int l,int r){
    if(l==r-1) {
        if(s[l]==s[r]) return 0;
        return 1;
    }
    if(mp[l][r]!=-1) return mp[l][r];
    int l1=dfs(l+1,r-1)|(s[l]<s[r]),l2=dfs(l+2,r)|(s[l]<s[l+1]);
    int r1=dfs(l+1,r-1)|(s[r]<s[l]),r2=dfs(l,r-2)|(s[r]<s[r-1]);
    int L=l1&l2,R=r1&r2;
    return mp[l][r]=L|R;
}
 
void solve(){
    cin>>(s+1);
    n=strlen(s+1);
    rep(i,1,n) rep(j,1,n) mp[i][j]=-1;
    if(dfs(1,n)) puts("Alice");
    else puts("Draw");
}  

E

题意:
有n个人前来吃饭,你可以给每个人放辣椒或黑胡椒,第\(i\)个人放辣椒或黑胡椒可分别获得\(a_i,b_i\)的美味值,你希望n个人获得的总的美味值最大,为此你将去商店去买这两种调味料。

一共有m家商店,对于第\(i\)家店,它们辣椒和黑胡椒均是按包麦,即一包辣椒有\(x_i\)份辣椒,一包黑胡椒有\(y_i\),你一次只能去一家商店去买,且买的时候总份数必须为n,即不能买多,\(x*x_i+y*y_i=n\)。求问对于每一家店,在该店购买调味时,可以带来的最大美味值,或者在这家店不能恰好买\(n\)份调味,输出\(-1\)

分析:

首先对于n个人的美味值,最大情况每个人都吃到了\(a_i,b_i\)中较大的那个,此时我们将人分为三类,\(a_i>b_i,a_i<b_i,a_i=b_i\),记它们人数分别为\(sa,sb,c\),当辣椒数量z在\([sa,sa+c]\)之间时,美味均可取最大值,否则当\(z>sa+c\)时,在\(a_i<b_i\)这一类中选较小的\(b_i-a_i\)来弥补差值,\(z<sa\)时同理,这里前缀和优化即可。因此当辣椒数量确定时,可以\(O(1)\)确定最大美味值,同时美味值关于辣椒数量的函数图像是一个梯形,即先上升,再不变,再下降,当\(c=0\)时,不变的区间退化为点。

对于去某一家点购买时,要满足\(x*x_i+y*y_i=n\),这是扩展欧几里得问题,直接求解即可,存在无解情况。
当有解时,求出特解后向一般解扩展,此时一般解需向梯形图像中间处靠,分类讨论即可。

具体实现时,将特解先转换为非负解,否则不合法。随后分为三类:
\(1. sa\leq x*x_i \leq sa+c\) 此时美味值直接达到最大,后续不用再进行
\(2. x*x_i< sa\),此时将x扩大至\(x*x_i\)最接近\(sa\)处,进行统计,然后越过\(sa\)再次统计
\(3. x*x_i>sa+c\),此时将x缩小至\(x*x_i\)最接近\(sa+c\)处,进行统计,然后越过\(sa+c\)再次统计

整个过程中,需要注意\(x<0\)和\(x*x_i>n\)的特殊情况,同时\(long long\)不能少。

ll gcd(ll a,ll b){return (!b)? a:gcd(b,a%b);}
void exgcd(ll &x,ll &y,ll a,ll b){
    if(b==0){x=1;y=0;return;}
    exgcd(x,y,b,a%b);
    ll temp=x;       
    x=y;y=temp-(a/b)*y;
    return;
}
ll a[maxn],b[maxn];
int c=0;
int sa=0,sb=0;
ll sum=0;
void gett(ll& ans,ll z){
    if(z>sa+c) ans=max(sum-b[z-sa-c],ans);
    else if(z<sa) ans=max(sum-a[sa-z],ans); 
    else ans=sum;
}
void solve(){
    ll n;n=read();
    rep(i,1,n){
        int x,y;scanf("%d %d",&x,&y);
        sum+=max(x,y);
        if(x>y) a[++sa]=(x-y);
        else if(x<y) b[++sb]=(y-x);
        else c++;
    }
    sort(a+1,a+1+sa);
    sort(b+1,b+1+sb);
    rep(i,1,sa) a[i]+=a[i-1];
    rep(i,1,sb) b[i]+=b[i-1];
    int m=read();
    while(m--){
        ll u,v;scanf("%lld %lld",&u,&v);
        ll w=gcd(u,v);
        if(n%w!=0) {puts("-1");continue;}
        ll x,y;
        exgcd(x,y,u,v);     
        x=x*n/w,y=y*n/w;
        ll t=v/w;
        if(x<0){
            int tep= (-x+t-1)/t;
            x+=tep*t;
            y-=tep*u/w;
        }
        if(y<0){
            int tep= (-y+u/w-1)/(u/w);
            x-=tep*t;
            y+=tep*u/w;
        }
        if(x<0||y<0) {puts("-1");continue;}
        ll ans=0,z=x*u;
        gett(ans,z);
        if(ans==sum){print(ans);pts;continue;}
        //向下
        if(z>sa+c){
            int tmp=z-sa-c;tmp/=(t*u);
            x-=tmp*t;z=x*u;
            if(z<=n&&x>=0) gett(ans,z);
            x-=t;z=x*u;
            if(z<=n&&x>=0) gett(ans,z);
        }
        if(ans==sum){print(ans);pts;continue;}
        //向上
        if(z<sa){
            int tmp=sa-z;tmp/=(t*u);
            x+=tmp*t;z=x*u;
            if(z<=n&&x>=0) gett(ans,z);
            x+=t;z=x*u;
            if(z<=n&&x>=0) gett(ans,z);
        }
        print(ans);pts;
    }
}  

标签:Educational,Rated,int,ll,Codeforces,ans,print,sa,rep
来源: https://www.cnblogs.com/Mr-leng/p/16674031.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有