码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces 1215

时间:2019-09-20 21:28:24      阅读:135      评论:0      收藏:0      [点我收藏+]

标签:目标   memset   vector   多少   else   scanf   mem   res   sum   

A.

分类讨论。

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=100003;
int main(){
    int a1,a2,k1,k2,n;
    cin>>a1>>a2>>k1>>k2>>n;
    if(k1>k2)swap(a1,a2),swap(k1,k2);
    int ans1=n/k1;
    if(ans1>a1)ans1=a1+(n-a1*k1)/k2;
    int tmp=n/a2,ans2;
    if(tmp<k2-k1)ans2=0;
    else{
        int m=n-a2*(k2-k1);
        tmp=(m+a1+a2-1)/(a1+a2);
        if(tmp<k1)ans2=0;
        else if(tmp==k1)ans2=(m%(a1+a2)==0?a1+a2:m%(a1+a2));
        else ans2=a1+a2;
    }
    cout<<ans2<<' '<<ans1;
    return 0;
}

B.

考虑前缀和的正负性。

C.

\(^{a\;a}_{b\;b}\rightarrow ^{a\;b}_{a\;b}\)
\(^{a\;b}_{b\;a}\rightarrow ^{a\;a}_{b\;b}\rightarrow ^{a\;b}_{a\;b}\)

执行完以上转换后,如果还没相等,那就不可能。

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=200003;
int n;
char s[maxn],t[maxn];
vector<int> u,v;
int main(){
    scanf("%d%s%s",&n,s+1,t+1);
    for(int i=1;i<=n;i++){
        if(s[i]=='a'&&t[i]=='b')u.push_back(i);
        if(s[i]=='b'&&t[i]=='a')v.push_back(i);
    }
    if(u.size()%2+v.size()%2==1){puts("-1");return 0;}
    int cnt=u.size()/2+v.size()/2+u.size()%2+v.size()%2;
    printf("%d\n",cnt);
    for(int i=0;i+1<int(u.size());i+=2){
        printf("%d %d\n",u[i],u[i+1]);
    }
    for(int i=0;i+1<int(v.size());i+=2){
        printf("%d %d\n",v[i],v[i+1]);
    }
    if(u.size()%2+v.size()%2){
        printf("%d %d\n%d %d\n",u.back(),u.back(),u.back(),v.back());
    }
    return 0;
}

D.

被叉掉了

Code

#include<bits/stdc++.h>
using namespace std;
const int maxn=200003;
int n,cnt0,cnt1,sum0,sum1;
char s[maxn];
int main(){
    scanf("%d%s",&n,s+1);
    for(int i=1;i<=n/2;i++){
        if(s[i]=='?')cnt0++;
        else sum0+=s[i]-48;
    }
    for(int i=n/2+1;i<=n;i++){
        if(s[i]=='?')cnt1++;
        else sum1+=s[i]-48;
    }
    if(sum0<sum1)swap(cnt0,cnt1),swap(sum0,sum1);
    int game=(cnt0+cnt1)/2;
    for(int i=1;i<=game;i++){
        if(cnt0){
            sum0+=9;
            cnt0--;
        }
        else{
            cnt1--;
            if(sum1+9>sum0)sum1+=9,swap(sum0,sum1),swap(cnt0,cnt1); // important
        }
        if(cnt1){
            sum1+=min(9,sum0-sum1);
            cnt1--;
        }
        else{
            cnt0--;
        }
    }
    puts(sum0==sum1?"Bicarp":"Monocarp");
    return 0;
}

E.

看到20,4s,考虑状压。
先预处理出 \(pre[i][j]\) 表示位置1到i有多少个元素等于j,然后在用其处理出 \(sum[i][j]\) 表示序列中每个等于i的元素的pre[j]之和。
然后 \(O(2^n*n^2)\) 状压dp,对于已处理的集合S和不在S中的i,我们的目标是把所有等于i的元素移到未处理元素的左边,S中元素的右边。这样它的贡献就是 \(\sum sum[i][j](j≠i,j?S)\)
有点类似统计逆序对。

Code

#include<bits/stdc++.h>
using namespace std;
typedef long long D;
const int maxn=400003,maxm=20,maxb=1<<maxm;
const D INF=0x3f3f3f3f3f3f3f3fll;
int n,a[maxn],pre[maxn][maxm];
D dp[maxb],sum[maxm][maxm];
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",a+i),a[i]--;
    for(int i=1;i<=n;i++){
        for(int j=0;j<maxm;j++)pre[i][j]=pre[i-1][j];
        pre[i][a[i]]++;
    }
    for(int i=1;i<=n;i++){
        for(int j=0;j<maxm;j++){
            sum[a[i]][j]+=pre[i][j];
        }
    }
    memset(dp,0x3f,sizeof(dp));
    dp[0]=0;
    for(int S=0;S<maxb;S++){
        for(int i=0;i<maxm;i++){
            if(!((S>>i)&1)){
                D res=0;
                for(int j=0;j<maxm;j++){
                    if(i!=j&&!((S>>j)&1)){
                        res+=sum[i][j];
                    }
                }
                dp[S|(1<<i)]=min(dp[S|(1<<i)],dp[S]+res);
            }
        }
    }
    printf("%lld\n",dp[maxb-1]);
    return 0;
}

Codeforces 1215

标签:目标   memset   vector   多少   else   scanf   mem   res   sum   

原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/11559535.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!