Educational Codeforces Round 9

链接:http://codeforces.com/contest/632

A. Grandma Laura and Apples

题意:n个人买苹果,每个人当前买一半的苹果,每个苹果p(偶数)元,输入half代表当前有偶数个苹果;halfplus代表当前有奇数个苹果,

因为是奇数,所以多的0.5个苹果送给这个人。

分析:逆着算钱,第i次的钱是i+1的两倍,如果是halfplus就加p/2。ans加上这次的钱就好了。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 50
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int a[Mn];
int main() {
    int n,m;
    string s;
    scanf("%d%d",&n,&m);
    ll ans=0,b=0;
    for(int i=1;i<=n;i++) {
        cin>>s;
        if(s[s.size()-1]=='s') {
            a[i]=1;
        } else {
            a[i]=0;
        }
    }
    for(int i=n;i>=1;i--)  {
        b=b*2;
        if(a[i]==1) b+=m/2;
        ans+=b;
    }
    cout<<ans<<endl;;
    return 0;
}


B. Alice, Bob, Two Teams

题意:给一个长度为n的数组p和串s,表示有p[i]个s[i],s串只包含‘A’,‘B’。有唯一一次操作,让串前缀或后缀全部反转(A->B,B->A),问B最多为多少。

分析:前后维护前缀和就好了。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 2000010
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
ll q[Mn],a[Mn],b[Mn];
char s[Mn];
int main() {
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        scanf("%I64d",&q[i]);
    }
    scanf("%s",s+1);
    ll ans=0;
    for(int i=1;i<=n;i++) {
        if(s[i]=='A') {
            a[i]+=a[i-1]+q[i];
            b[i]=b[i-1];
        } else {
            b[i]+=b[i-1]+q[i];
            a[i]=a[i-1];
        }
    }
    ans=b[n];
    for(int i=1;i<=n;i++) {
        if(a[i]>b[i]) {
            ans=max(ans,a[i]+b[n]-b[i]);
        }
    }
    CLR(a,0);CLR(b,0);
    for(int i=n;i>=1;i--) {
        if(s[i]=='A') {
            a[i]+=a[i+1]+q[i];
            b[i]=b[i+1];
        } else {
            b[i]+=b[i+1]+q[i];
            a[i]=a[i+1];
        }
    }
    for(int i=n;i>=1;i--) {
        if(a[i]>b[i]) {
            ans=max(ans,a[i]+b[1]-b[i]);
        }
    }
    cout<<ans<<endl;
    return 0;
}


C. The Smallest String Concatenation

题意:给你n个字符串,输出这n个串组合成的字符串字典序最小。

分析:直接排序输出是按每个串本身字典序排,整体并不是最小的。由于是要组合后的,所以我们定义排序规则 (a+b)<(b+a)。这样就可以让整体最小了。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 1001000
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
bool cmp(string a,string b) {
    return (a+b)<(b+a);
}
string s[Mn];
int main() {
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        cin>>s[i];
    }
    sort(s+1,s+1+n,cmp);
    for(int i=1;i<=n;i++) cout<<s[i];
    return 0;
}


D. Longest Subsequence

题意:给出n个数,让你输出l,k,n个数中k个数的LCM,要求k最大的最小l。

分析:由于LCM不超过m(m<10^6),记录每个数的个数,从m到1,枚举这些数的倍数,a[i*j]+=a[i].最后找出最大。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 1000010
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int a[Mn],b[Mn];
int main() {
    int n,m,x;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) {
        scanf("%d",&b[i]);
        if(b[i]<=m) a[b[i]]++;
    }
    for(int i=m;i>=1;i--) {
        if(a[i]) {
            for(int j=2;i*j<=m;j++) {
                a[i*j]+=a[i];
            }
        }
    }
    int ans=0,pos=0;
    for(int i=1;i<=m;i++) {
        if(a[i]>ans) {
            ans=a[i];
            pos=i;
        }
    }
    if(pos) {
        cout<<pos<<" "<<ans<<endl;
        for(int i=1;i<=n;i++) {
            if(pos%b[i]==0) cout<<i<<" ";
        }
    }else cout<<1<<" "<<0<<endl;
    return 0;
}


E. Thief in a Shop

题意:不会。。。。

分析:

代码:

F. Magic Matrix

题意:给你一个n*n的矩阵,要你判断是否满足a[i][j]=0,a[i][j]=a[j][i],对于任意k满足a[i][j]<=max(a[i][k],a[j][k]).

分析: 由于对称,可以最后一个条件转换成a[i][j]<=max(a[i][k],a[k][j]),将矩阵上的a[i][j]看成点i到点j边长为a[i][j]。

然后就可以发现这个条件变成,a[i][j]小于等于i到j路径上的每条边。求个最小生成树。

代码:

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<string>
#include<vector>
#include<queue>
#include<cmath>
#include<stack>
#include<set>
#include<map>
#define INF 0x3f3f3f3f
#define Mn 2510
#define Mm 2000005
#define mod 1000000007
#define CLR(a,b) memset((a),(b),sizeof((a)))
#define CPY(a,b) memcpy ((a), (b), sizeof((a)))
#pragma comment(linker, "/STACK:102400000,102400000")
#define ul u<<1
#define ur (u<<1)|1
using namespace std;
typedef long long ll;
int vt[Mn*Mn/2];
int a[Mn][Mn],cnt=0,n,pre[Mn];
bool cmp(int x,int y) {
    return a[x/n][x%n]<a[y/n][y%n];
}
int find(int x) {
    if(x!=pre[x]) return pre[x]=find(pre[x]);
    return pre[x];
}
int main() {
    scanf("%d",&n);
    for(int i=1;i<=n;i++) {
        for(int j=1;j<=n;j++)
            scanf("%d",&a[i][j]);
        pre[i]=i;
    }
    for(int i=1;i<=n;i++) {
        if(a[i][i]) {printf("NOT MAGIC\n");return 0;}
        for(int j=1;j<=n;j++) {
            if(a[i][j]!=a[j][i]) {printf("NOT MAGIC\n");return 0;}
            if(i>j) vt[cnt++]=i*n+j;
        }
    }
    int k=0;
    sort(vt,vt+cnt,cmp);
    for(int i=0;i<cnt;i++) {
        if(i<cnt&&a[vt[i]/n][vt[i]%n]==a[vt[i+1]/n][vt[i+1]%n]) continue;
        for(int j=k;j<=i;j++)
            if(find(vt[j]/n)==find(vt[j]%n)) {printf("NOT MAGIC\n");return 0;}
        for(int j=k;j<=i;j++) {
            int x=find(vt[j]/n);
            int y=find(vt[j]%n);
            if(x!=y) pre[x]=y;
        }
        k=i+1;
    }
    printf("MAGIC\n");
    return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值