Educational Codeforces Round 9

来源:互联网 发布:齐白石真迹价格 知乎 编辑:程序博客网 时间:2024/05/17 01:09

链接: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
原创粉丝点击