• NOIP 数字游戏


    描述

    丁丁最近沉迷于一个数字游戏之中。这个游戏看似简单,但丁丁在研究了许多天之后却发觉原来在简单的规则下想要赢得这个游戏并不那么容易。游戏是这样的,在你面前有一圈整数(一共n个),你要按顺序将其分为m个部分,各部分内的数字相加,相加所得的m个结果对10取模后再相乘,最终得到一个数k。游戏的要求是使你所得的k最大或者最小。

    格式

    输入格式

    输入文件第一行有两个整数,n(1≤n≤50)和m(1≤m≤9)。以下n行每行有个整数,其绝对值不大于104,按顺序给出圈中的数字,首尾相接。

    输出格式

    输出文件有两行,各包含一个非负整数。第一行是你程序得到的最小值,第二行是最大值。

    样例1

    样例输入1[复制]

     
    4 2
    4
    3
    -1
    2

    样例输出1[复制]

     
    7
    81

    限制

    各个测试点1s,128MB

    分析:

      f_max[i][j]表示前i个数,分成j分的最大值

      f_min[i][j]表示前i个数,分成j分的最小值

      下面给出两种转移顺序,第一种是错的,第二种是对的,两者只有顺序不同。。。

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cmath>
     5 #include<cstring>
     6 #include<algorithm>
     7 using namespace std;
     8 typedef long long LL;
     9 const LL MOD=10;
    10 const LL MAX_N=1000;
    11 const LL MAX_M=100;
    12 LL N,M;
    13 LL a[MAX_N];
    14 LL sum[MAX_N];
    15 LL b[MAX_N];
    16 LL f_max[MAX_N][MAX_M];//f[i][j]前 i个数 ,分成 j部分的最大值 
    17 LL f_min[MAX_N][MAX_M];//f[i][j]前 i个数 ,分成 j部分的最小值
    18 void calc();
    19 void move_a(LL);
    20 LL MAX;
    21 LL MIN=0x3f3f3f3f;
    22 int main(){
    23     
    24     scanf("%lld%lld",&N,&M);
    25     for(LL i=1;i<=N;i++){
    26         scanf("%lld",&a[i]);
    27         b[i]=a[i];
    28         sum[i]=sum[i-1]+b[i];
    29     }
    30     
    31     calc();
    32     for(LL i=1;i<=M+1;i++){//序列向后退 i个单位 
    33         move_a(i);
    34         calc();
    35     }
    36     
    37     cout<<MIN<<endl<<MAX<<endl;
    38     
    39     return 0;
    40 }
    41 void calc(){
    42     memset(f_min,0,sizeof(f_min));
    43     memset(f_max,0,sizeof(f_max));
    44     memset(f_min,0x3f3f3f3f,sizeof(f_min));
    45     f_max[0][0]=1;
    46     f_min[0][0]=1;
    47     for(LL i=1;i<=N;i++){
    48         f_max[i][1]=(sum[i]%MOD+MOD)%MOD;
    49         f_min[i][1]=(sum[i]%MOD+MOD)%MOD;
    50     }
    51     /* 这个是错的 
    52     for(LL i=2;i<=N;i++){//前 i个数 
    53         for(LL j=2;j<=M&&j<=i;j++){//分成 j部分 
    54             for(LL k=j-1;k<i;k++){//从 k后截断一次 
    55                 f_max[i][j]=max(f_max[i][j], (f_max[k][j-1]*(((sum[i]-sum[k])%MOD+MOD)%MOD)));
    56                 f_min[i][j]=min(f_min[i][j], (f_min[k][j-1]*(((sum[i]-sum[k])%MOD+MOD)%MOD)));
    57             }
    58         }
    59     }
    60     */
    61     //下面这个才是对的    
    62     for(LL j=2;j<=M;j++){//分成 j部分 
    63         for(LL i=j;i<=N;i++){//前 i个数 
    64             for(LL k=j-1;k<i;k++){//从 k后截断一次 
    65                 f_max[i][j]=max(f_max[i][j], (f_max[k][j-1]*(((sum[i]-sum[k])%MOD+MOD)%MOD)));
    66                 f_min[i][j]=min(f_min[i][j], (f_min[k][j-1]*(((sum[i]-sum[k])%MOD+MOD)%MOD)));
    67             }
    68         }
    69     }
    70     
    71     MAX=max(MAX,f_max[N][M]);
    72     MIN=min(MIN,f_min[N][M]);
    73 
    74 }
    75 void move_a(LL x){
    76     memset(b,0,sizeof(b));
    77     memset(sum,0,sizeof(sum));
    78     LL now;
    79     for(LL i=1;i<=N;i++){
    80         now=i+x;
    81         if(now>N){
    82             now%=N;
    83         }
    84         b[now]=a[i];
    85     }
    86     for(LL i=1;i<=N;i++){
    87         sum[i]=sum[i-1]+b[i];
    88     }
    89 }

      

  • 相关阅读:
    真正的Java学习从入门到精通
    Java学习从入门到精通(1) [转载]
    Java Learning Path(三)过程篇
    Java Learning Path(五)资源篇
    Java Learning Path(四) 方法篇
    浅析Java语言中两种异常的差别
    JDK,JRE,JVM区别与联系
    JAVA敏捷开发环境搭建
    谈谈WEB开发中的苦大难字符集问题
    java读取clob字段的几种方法
  • 原文地址:https://www.cnblogs.com/CXCXCXC/p/4779167.html
Copyright © 2020-2023  润新知