Codeforces Round #289 (Div. 2, ACM ICPC Rules)

A. Maximum in Table

#include <iostream>
#include <string.h>
#include <stdio.h>

using namespace std;

int a[20][20];

int main()
{
    int n;
    int ans=1;
    cin>>n;
    for(int i=0;i<n;i++) a[0][i]=1;
    for(int i=0;i<n;i++) a[i][0]=1;
    for(int i=1;i<n;i++)
    for(int j=1;j<n;j++){
        a[i][j]=a[i-1][j]+a[i][j-1];
        ans=max(ans,a[i][j]);
    }
    printf("%d\n",ans);

    return 0;
}

B. Painting Pebbles

有n堆个石头,c种颜色,第i堆石头有ai个,能否给全部石头涂色并使得任意两堆石头中涂某种颜色的石头个数的差不大于1。

贪心 ,考虑最大堆和最小堆的石头,两者之差就是多出来的石头,如果多出来的石头数量大于颜色的种类数,根据鸽巢原理,某种颜色一定会出现两次,则不符合。如果可以实现,将颜色和石头编号,然后石头编号对应颜色编号就可以输出一种方案。

#include <iostream>
#include <stdio.h>
#include <string.h>

using namespace std;

int ans[105][105],a[105];

bool judge(int a,int b,int k){
     int tmp;
     tmp=(a-b)/k;
     if((a-b)%k) tmp++;
     if(tmp>1) return false;
     return true;
}


int main()
{
    int n,k;
    int maxx,minn;
    maxx=-1;
    minn=200;
    cin>>n>>k;
    for(int i=0;i<105;i++){
        for(int j=0;j<105;j++){
            ans[i][j]=j%k+1;
        }
    }

    for(int i=0;i<n;i++) {
        cin>>a[i];
        maxx=max(maxx,a[i]);
        minn=min(minn,a[i]);
    }
    if(judge(maxx,minn,k)){
        printf("YES\n");
        for(int i=0;i<n;i++){
            for(int j=0;j<a[i];j++){
                printf("%d",ans[i][j]);
                if(j==a[i]-1) printf("\n");
                else printf(" ");
            }
        }
    }
    else printf("NO\n");
    return 0;
}

C. Sums of Digits

题目大意就是a这个序列是一个递增序列,bi是ai的十进制每一位数字之和,给序列bi,求ai,并且an为最小。

贪心+构造,将bi从低位到高位进行分配能使ai最小,但是还要满足a为递增,那么就分两种情况,一种是bi>bi-1,只需要对上一个ai从低位到高位加上bi-bi-1即可(如果某位为9则该位不可加,否则总数就不对了),另外一种情况是bi<=bi-1,这时候就要找到(bi)-1能够构造的最小的大于ai-1的数字,也就是希望ai和ai-1有尽量长的前缀(满足递增的情况下),方法就统计高位的和,到和即将大于或等于bi之前,这时候对高位+1(为了满足递增),低位再按从低到高分配,注意细节即可。

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

char dp[305][400];

int in[305];

int main()
{
    int n;
    cin>>n;
    memset(dp,'0',sizeof(dp));
    for(int i=0;i<n;i++){
        scanf("%d",&in[i]);
    }
    int c,cou,tmp;
    cou=0;
    tmp=in[0];
    while(1){
      if(tmp<=9){
        dp[0][cou++]=tmp+'0';
        dp[0][cou]=0;
        break;
      }
      else{
        dp[0][cou++]='9';
        tmp-=9;
      }
    }
    int len;
    for(int i=1;i<n;i++){
        if(in[i]>in[i-1]){
          tmp = in[i] - in[i-1];
          len=strlen(dp[i-1]);
          for(int j=0;j<len;j++){
            if(tmp==0){
                dp[i][j]=dp[i-1][j];
                continue;
            }
            if(dp[i-1][j]<'9'){
                if(tmp>'9'-dp[i-1][j]){
                    dp[i][j]='9';
                    tmp-='9'-dp[i-1][j];
                }
                else{
                    dp[i][j]=dp[i-1][j]+tmp;
                    tmp = 0;
                }
            }
            else{
                dp[i][j] = '9';
            }
          }
          while(tmp){
            if(tmp<=9){
                dp[i][len++]='0'+tmp;
                break;
            }
            else{
                dp[i][len++]='9';
                tmp-=9;
            }
          }
          dp[i][len]=0;
        }//if(in[i]>in[i-1])
        else{
            cou = 0;
            len = strlen(dp[i-1]);
            int j;
            for(j = len - 1; j>=0; j--){
                if(cou+dp[i-1][j]-'0'<in[i]){
                    cou+=dp[i-1][j]-'0';
                    dp[i][j]=dp[i-1][j];
                }
                else{
                    break;
                }
            }
            int flag;
            for(j=j+1;j<=len;j++){
                if(dp[i-1][j]==0){
                    dp[i][j]='1';
                    flag = j-1;
                    len++;
                    break;
                }
                if(dp[i-1][j]!='9'){
                    dp[i][j]=dp[i-1][j]+1;
                    flag = j-1;
                    break;
                }

            }
            dp[i][len]=0;
            cou = 0;
            for(j = flag+1;j<len;j++) cou+=dp[i][j]-'0';
            tmp = in[i] - cou;
            cou=0;
            while(1){
              if(tmp<=9){
                 dp[i][cou++]=tmp+'0';
                 tmp=0;
                 break;
              }
              else{
                    dp[i][cou++]='9';
                    tmp-=9;
                  }
            }
            for(j = cou;j <= flag;j++){
                dp[i][j]='0';
            }
        }
    }
    for(int i = 0;i<n;i++){
        len = strlen(dp[i]);
        for(int j=len-1;j>=0;j--){
            printf("%c",dp[i][j]);
        }
        if(i!=n-1) printf("\n");
    }
    return 0;
}
E. Pretty Song

按子串的长度为一类进行求和,求和有一个小技巧,将o(n^2)变成线性的复杂度。

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define N 500005
#define LL long long
char txt[N];
double save[N],tmp[N];

bool judge(char a){
     if(a=='I') return true;
     if(a=='E') return true;
     if(a=='A') return true;
     if(a=='O') return true;
     if(a=='U') return true;
     if(a=='Y') return true;
     else return false;
}

int main()
{
    cin>>txt;
    int len;
    double ans;
    len=strlen(txt);
    if(judge(txt[0])) save[0]=1;
    for(int i=1;i<len;i++){
            save[i]=save[i-1];
        if(judge(txt[i])) save[i]++;
    }
    tmp[0]=save[len-1];
    for(int i=1;i<len;i++){
        tmp[i]=tmp[i-1]+(save[len-i-1]-save[i-1]);
    }
    ans=0;
    for(int i=0;i<len;i++){
        ans+=tmp[i]/(double)(i+1);
    }
    printf("%.7lf\n",ans);
    return 0;
}

F. Progress Monitoring

树形dp,将节点分为某个结点的第一个子树和其他子树,然后用乘法原理计算。

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;
#define N 505
#define LL long long
const int Mod = 1e9+7;
LL dp[N][N];
int in[N];

int main(){
    int n;
    cin>>n;
    for(int i=0;i<n;i++){
        cin>>in[i];
    }
    memset(dp,0,sizeof(dp));
    for(int i=0;i<n;i++){
        dp[i][i]=1;//长度为1的只有一种树结构
    }

    for(int i=n-2;i>=0;i--){
        for(int j = i+1;j<n;j++){
            dp[i][j] = dp[i + 1][j];//只有一棵子树的时候
            for(int k=i+1;k<=j;k++){
                if(in[i+1]<in[k]){
                    dp[i][j]=(dp[i][j]+dp[i+1][k-1]*dp[k-1][j])%Mod;
                }
            }
        }
    }
    printf("%I64d\n",dp[0][n-1]);
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值