Educational Codeforces Round 9

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

problemA:给定n,p,表示有n个人买了苹果(每次买剩下苹果的一半),p表示苹果的单价且为偶数,接下来n行字符串half表示当时第i个人买的时候苹果数为偶数,halfplus表示第i个人买的时候为奇数个,这个时候卖完之后剩的半个苹果会当礼物送给这个人。求一个卖了多少钱。O(n)

分析:逆着算出总苹果数,再顺着算一下钱即可。

代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=1000010;
const int MAX=151;
const int MOD1=1000007;
const int MOD2=100000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=1000000009;
const ll INF=10000000010;
typedef unsigned long long ull;
char s[10];
int a[50];
int main()
{
    int i,n,p;
    ll sum=0,ans=0;
    scanf("%d%d", &n, &p);
    for (i=1;i<=n;i++) {
        scanf("%s", s);
        if (strlen(s)>4) a[i]=1;
        else a[i]=0;
    }
    for (i=n;i>0;i--)
    if (a[i]) sum=sum*2+1;
    else sum<<=1;
    for (i=1;i<=n;i++)
    if (sum&1) {
        ans+=sum/2*p+p/2;sum>>=1;
    } else {
        ans+=sum/2*p;sum>>=1;
    }
    printf("%I64d\n", ans);
    return 0;
}

problemB:给定一个长度为n的只含'A'和'B'的字符串,然后给出这n个位置的价值p[i]。最多进行一次以下操作:选择一个字符串的前缀或后缀,使得这个子串全部翻转(A->B,B->A)。求最后在所有字符'B'对于位置的价值之和的最大值。O(n)

分析:正反维护下前缀和即可。

代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=500010;
const int MAX=151;
const int MOD1=1000007;
const int MOD2=100000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=1000000007;
const ll INF=10000000010;
typedef unsigned long long ull;
char s[N];
ll y[N],p[N],sum[N];
int main()
{
    int i,n;
    ll ans=0;
    scanf("%d", &n);
    for (i=1;i<=n;i++) scanf("%I64d", &p[i]);
    scanf("%s", s);
    y[0]=sum[0]=0;
    for (i=1;i<=n;i++)
    if (s[i-1]=='B') {
        y[i]=y[i-1]+p[i];sum[i]=sum[i-1]-p[i];
    } else {
        y[i]=y[i-1];sum[i]=sum[i-1]+p[i];
    }
    ans=y[n];
    for (i=1;i<=n;i++) {
        ans=max(ans,y[n]+sum[i]);
        ans=max(ans,y[n]+sum[n]-sum[i-1]);
    }
    printf("%I64d\n", ans);
    return 0;
}

problemC:给定n个字符串,将这n个字符串接成一个长串,求字典序最小的长串。

分析:假设s[i],s[j]相邻且所有字符串除了s[i],s[j]都已经排好了,判断i在前好还是j在前好,判断一下s[i]+s[j]<s[j]+s[i]即可。排序。O(50*nlogn)

代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=50010;
const int MAX=151;
const int MOD1=1000007;
const int MOD2=100000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=1000000000;
const ll INF=10000000010;
typedef unsigned long long ull;
string s[N];
int cmd(string a,string b) {
    string ab=a+b;
    string ba=b+a;
    return ab<ba;
}
int main()
{
    int i,n;
    scanf("%d", &n);
    for (i=1;i<=n;i++) cin>>s[i];
    sort(s+1,s+n+1,cmd);
    for (i=1;i<=n;i++) cout<<s[i];
    cout<<endl;
    return 0;
}


problemD:给定n,m,然后给定n个数a[i]。要求选出最多个数的a[i]同时使得LCM(a[i])<=m。多组解时输出LCM最小的那组。

分析:用数组统计下即可,然后从后往前用数x去更新x的倍数。O(n+mlogm)

代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=1000010;
const int MAX=151;
const int MOD1=1000007;
const int MOD2=100000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=1000000007;
const ll INF=10000000010;
typedef unsigned long long ull;
int a[N],dp[N];
int main()
{
    int i,j,n,m,w,mx=0;
    scanf("%d%d", &n, &m);
    memset(dp,0,sizeof(dp));
    for (i=1;i<=n;i++) {
        scanf("%d", &a[i]);
        if (a[i]<=m) dp[a[i]]++;
    }
    for (i=m;i>0;i--)
    if (dp[i]) {
        for (j=2*i;j<=m;j+=i) dp[j]+=dp[i];
    }
    for (i=1;i<=m;i++)
    if (dp[i]>mx) { mx=dp[i];w=i; }
    if (!mx) printf("1 0\n");
    else {
        printf("%d %d\n", w, mx);
        for (i=1;i<=n;i++)
        if (w%a[i]==0) printf("%d ", i);
        printf("\n");
    }
    return 0;
}

problemE:给定n,k,然后n个数a[i]。求n个数中选k个数加起来能组成多少个不同的数。

分析:用FFT处理。我还不会。下次补。

代码:

补在另一篇博客了:http://blog.csdn.net/fsss_7/article/details/50950203


problemF:给定一个n*n的矩阵,要求你判断是否满足以下条件:(1)a[i][i]=0。(2)a[i][j]==a[j][i]&&i!=j。(3)对于任意a[i][j]<=max(a[i][k],a[j][k])。

分析:很明显我们要处理的难点在于条件3。我们可以将条件3看成对于任意3个点i,j,k恒成立三角形的一边小于等于另外两边的最大值,然后我们可以将这个条件推到4个点i,j,k,l恒成立a[i][l]<=max(a[i][j],a[j][k],a[k][l]),5个点...。然后我们发现其实就是求一个最小生成树,然后对于任意两点i,j在树上的路径上的最大值x>=a[i][j]。O(n^2logn)

代码:

#include<map>
#include<set>
#include<cmath>
#include<queue>
#include<bitset>
#include<math.h>
#include<cstdio>
#include<vector>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
#pragma comment(linker, "/STACK:102400000,102400000")
using namespace std;
const int N=2510;
const int MAX=151;
const int MOD1=1000007;
const int MOD2=100000009;
const double EPS=0.00000001;
typedef long long ll;
const ll MOD=1000000007;
const ll INF=10000000010;
typedef unsigned long long ull;
struct node {
    int u,v,w;
    node () {}
    node (int u,int v,int w):u(u),v(v),w(w) {}
    bool operator < (const node a) const {
        return a.w<w;
    }
}g;
int q[N],d[N],a[N][N],mx[N][N];
priority_queue<node>Q;
int main()
{
    int i,j,n,k=0,bo=1;
    scanf("%d", &n);
    for (i=1;i<=n;i++)
        for (j=1;j<=n;j++) scanf("%d", &a[i][j]);
    for (i=1;i<=n;i++)
    if (a[i][i]) bo=0;
    for (i=1;i<=n;i++)
        for (j=1;j<i;j++)
        if (a[i][j]!=a[j][i]) bo=0;
    if (!bo) printf("NOT MAGIC\n");
    else {
        memset(q,0,sizeof(q));
        memset(mx,0,sizeof(mx));
        q[1]=1;d[++k]=1;
        for (i=2;i<=n;i++) Q.push(node(1,i,a[1][i]));
        while (!Q.empty()) {
            if (k>=n) break ;
            g=Q.top();Q.pop();
            if (q[g.v]) continue ;
            q[g.v]=1;d[++k]=g.v;
            for (i=1;i<k;i++)
            mx[d[i]][g.v]=mx[g.v][d[i]]=max(mx[d[i]][g.u],g.w);
            for (i=1;i<=n;i++)
            if (!q[i]) Q.push(node(g.v,i,a[g.v][i]));
        }
        for (i=1;i<=n;i++)
            for (j=1;j<i;j++)
            if (mx[i][j]<a[i][j]) bo=0;
        if (bo) printf("MAGIC\n");
        else printf("NOT MAGIC\n");
    }
    return 0;
}



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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值