• 能被15整除的最大整数 BITOJ 网络教室


    能被15整除的最大整数

    sources:http://cms.bit.edu.cn/moodle/mod/programming/view.php?a=5539

    能被15整除的最大整数

    成绩: 5 / 折扣: 0.8
    给定一个只包含数字 [0..9] 的字符串,求使用字符串中的某些字符,构造一个能够被15整除的最大整数。注意,字符串中的每个字符只能使用一次。 
    输入:程序从标准输入读入数据,每行数据由一串数字组成,长度为1到1000。
    输出:针对每一行输入,输出一个结果,每个结果占一行。如果无法构造出能够被15整除的整数,请输出impossible。


    测试输入帮助,input (新窗口)期待的输出帮助,expectedoutput (新窗口)时间限制帮助,timelimit (新窗口)内存限制帮助,memlimit (新窗口)额外进程帮助,nproc (新窗口)
    测试用例 1 以文本方式显示
    1. 1↵
    2. 01431↵
    以文本方式显示
    1. impossible↵
    2. 43110↵

    思路,题目有意降低难度,为什么是15 而不是18 16 之类的,因为,15=3*5,这个就好办了。学过数论的都知道:

    定理:如果15可以整除X(即X是15的倍数),那么5也可整除X,3也可以整除X。于是这道题目就变得简单。

    5整除X,于是,X的末尾只能是0或者5。

    3整除X,于是所有的数字之和必须是3的倍数。这就是为什么题目出一个15。

    说一下思路:用cnt数组存放每个字符(0~9)出现的次数。stack存放,mod=1 、2 的数字是哪些,排个序存放。

    然后,先用上所有的数字,不满足的话,一个个剔除。从小到大剔除,遍历所有剔除的方案,还是不满足,直接impossible。

    ps:15可以整除0.,笔者因为介个,WA了N次。

    欢迎转载,著名出处。

    View Code
      1 #include<stdio.h>
    2 #include<stdlib.h>
    3 #include<string.h>
    4 char str[1005],ans0[1005],ans5[1005];//str为输入字符串,ans0、5为带输出的字符串
    5 int cnt[10],stack[3][1005],sum;//sum,表示所有字符的数字之和,cnt[5]=6 表示 5出现过6次数,stack[2][4]表示符合mod=2 的第4个数,从小到大。
    6 void into_str(char str[],int tag)
    7 {//将cnt[]里面的数字按大小存放在字符串str里面,方便输出,tag标记一下末尾的数字
    8 int e,j,k;
    9 for(e=0,k=9;k>=0;k--)
    10 for(j=0;j<cnt[k];j++)
    11 str[e++]=k+'0';
    12
    13 if(tag==0)str[e++]='0';
    14 else str[e++]='5';
    15 str[e]='\0';
    16 }
    17 int solve(char str[],int tag)
    18 {//剔除掉某些多余的数字,剔除的目的是为了改变cnt,然后将cnt中的数字塞进字符串str里面
    19 int k;
    20 switch(sum%3)//sum是所有数字之和
    21 {
    22 case 0://余0 表示不需要剔除数字
    23 into_str(str,tag);return 1;
    24 case 1://余1 表示需要剔除余数为1的数字,也可以剔除 两个2. ect
    25 if(stack[1][0]!=0)//stack[1][0] 表示余数为1的数字的个数(个人习惯)
    26 {//stack里面的数字已经按从小打到排序,可以剔除的话,当然是剔除第一个 stack[1][1];
    27 cnt[stack[1][1]]--;into_str(str,tag);cnt[stack[1][1]]++;
    28 return 1;
    29 }
    30 else if(stack[2][0]!=0)
    31 if(tag == 0)
    32 if(stack[2][0]==1)return 0;
    33 else{
    34 cnt[stack[2][1]]--;cnt[stack[2][2]]--;into_str(str,tag);
    35 cnt[stack[2][1]]++;cnt[stack[2][2]]++;return 1;
    36 }
    37 else//tag=5
    38 if(stack[2][0]<=2)return 0;
    39 else
    40 {//剔除两个 mod=2 的数字,由于5存在与stack中,所以会繁琐一点
    41 for(k=1;k<=stack[2][0];k++)
    42 if(stack[2][k]!=-1){cnt[stack[2][k]]--;break;}
    43 for(k++;k<=stack[2][0];k++)
    44 if(stack[2][k]!=-1){cnt[stack[2][k]]--;break;}
    45 //转换成字符串
    46 into_str(str,tag);
    47 //恢复刚刚的改变
    48 for(k=1;k<=stack[2][0];k++)
    49 if(stack[2][k]!=-1){cnt[stack[2][k]]++;break;}
    50 for(k++;k<=stack[2][0];k++)
    51 if(stack[2][k]!=-1){cnt[stack[2][k]]++;break;}
    52 return 1;
    53 }
    54 else return 0;//mod=1 or mod=2 都不能满足,说明impossible return 0
    55 case 2://余数为2
    56 if(stack[2][0]!=0)
    57 if(tag==0)
    58 {cnt[stack[2][1]]--;into_str(str,tag);cnt[stack[2][1]]++;return 1;}
    59 else//tag==5 and 5 is in stack[2]
    60 if(stack[2][0]>=2)
    61 {
    62 for(k=1;k<=stack[2][0];k++)
    63 if(stack[2][k]!=-1){cnt[stack[2][k]]--;break;}
    64 into_str(str,tag);
    65 for(k=1;k<=stack[2][0];k++)
    66 if(stack[2][k]!=-1){cnt[stack[2][k]]++;break;}
    67 return 1;
    68 }
    69 //if it did not return here ,then goto mod 1
    70 //mod 1
    71 if(stack[1][0]<=1)return 0;// mod 1 or mod 2 都不满足
    72 else
    73 {//最前面的两个就是最小的,直接剔除
    74 cnt[stack[1][1]]--;cnt[stack[1][2]]--;into_str(str,tag);
    75 cnt[stack[1][1]]++;cnt[stack[1][2]]++;return 1;
    76 }
    77 default :break;
    78 }
    79 }
    80
    81 int main()
    82 {
    83 int i,j,n,tp0,tp5,index;//tp0、5 记录末尾为 0、5 的情况是不是可行。初始化为0
    84 while(~scanf("%s",str))
    85 {
    86 memset(cnt,0,sizeof(cnt));
    87 memset(stack,0,sizeof(stack));
    88 memset(ans0,0,sizeof(ans0));
    89 memset(ans5,0,sizeof(ans5));
    90 tp0=tp5=0;
    91 n=strlen(str);
    92 for(sum=i=0;i<n;i++)
    93 {
    94 index=str[i]-'0';
    95 cnt[index]++;
    96 sum+=index;
    97 }
    98 for(i=0;i<10;i++)
    99 for(j=0;j<cnt[i];j++)
    100 if(i%3) stack[i%3][++stack[i%3][0]]=i;//只需记录余数为1 or 2,mod=0 不需要记录,mod=0 踢不踢除都没关系
    101 else continue;
    102
    103 if(cnt[0]==0 && cnt[5]==0){printf("impossible\n");continue;}
    104 if(cnt[0]!=0)
    105 {
    106 cnt[0]--;
    107 tp0=solve(ans0,0);
    108 cnt[0]++;
    109 }
    110 if(cnt[5]!=0)
    111 {
    112 cnt[5]--;//5作为末尾的元素,需要在stack中标记一下,避免重复使用
    113 for(j=1;j<=stack[2][0];j++)if(stack[2][j]==5){stack[2][j]=-1;break;}
    114
    115 tp5=solve(ans5,5);
    116 cnt[5]++;
    117 //恢复
    118 for(j=1;j<=stack[2][0];j++)if(stack[2][j]==-1){stack[2][j]=5;break;}
    119 }
    120 if(tp0==0 && tp5==0){printf("impossible\n");continue;}
    121 if(tp0==0 || strcmp(ans0,ans5)<0)
    122 if(ans5[0]=='0')//{printf("impossible\n");continue;} 笔者曾经以为15不整除0,所以输出impossible,结果wa了N次
    123 {printf("0\n");continue;}
    124 else {printf("%s\n",ans5);continue;}
    125 if(tp5==0 || strcmp(ans0,ans5)>=0)
    126 if(ans0[0]=='0')//{printf("impossible\n");continue;}
    127 {printf("0\n");continue;}
    128 else {printf("%s\n",ans0);continue;}
    129 }
    130 return 0;
    131 }



  • 相关阅读:
    Java 泛型
    face_recognition
    用于图像分割的卷积神经网络:从R-CNN到Mark R-CNN
    OpenCV探索
    基于深度学习的目标检测技术演进:R-CNN、Fast R-CNN、Faster R-CNN
    卷积神经网络CNN总结
    (4)Smali系列学习之Smali语法详解内部类
    log4j的配置信息
    C#的async和await
    Java魔法堂:String.format详解
  • 原文地址:https://www.cnblogs.com/kevinkitty/p/iee.html
Copyright © 2020-2023  润新知