zoukankan      html  css  js  c++  java
  • Prime Permutation

                 Prime Permutation

    原题地址: http://codeforces.com/problemset/problem/123/A

    题目大意:

          给你一个字符串(只包含小写字母),从1开始存放。定义长度为|s|,有1<=|s|<=1000。要求通过调整字符在字符串中的位置,使得:       设p为小于等于|s|的素数,有s[p]=s[p*i] (p*i<=|s|),能够完成该项任务就输出YES和调整后的字符串,不能则输出NO。

    大致思路:

          由于s[p]=s[p*i],如果|s|足够大,便有: s[2]=s[4]=s[6]=s[8]…  s[3]=s[6]=s[9]…  s[5]=s[10]…

    所以s[3]=s[6]=s[2]=s[10]=s[5],也就是当|s|增大时,就把前面的素数连在一起,所以要求给定的数组中绝大部分的字符应该是一样的,所以我们可以定义一个变量mt,用来记录最大的出现次数,如果mt小于某个值,就输出NO,大于就输出YES。现在的任务就是求出对应字符串长度的这个值,很明显|s+1|的对应值可以由|s|的对应值求来。

          现在我们定义一个数组dp[1010],dp[i]记录长度为i的字符串重复字符的最少个数。比如: aabbb 长度为5,有s[2]=s[4],所以dp[5]=2,显然,该字符串可以输出YES。

        可以想见: 如果i+1是一个素数,那么dp[i+1]=dp[i],如果i+1不是素数,有dp[i+1]=dp[i]+1;但单单这样是不准确的,因为比如dp[5]=2,5+1不是一个素数,但它的出现不仅影响到本身:s[2]=s[6],还通过s[3]=s[6]影响到3,所以实际上dp[6]=4,即2、3、4、6四位应该是相同的。也就是每当到一定的长度,总会把一些底层素数连在一起,到6时就把2、3连在一起,到10就把2、5连在一起,到14就把2、7连在一起,于是我们可以初始化dp[i*2]=1,i为素数。

    AC代码:

     1 #include<stdio.h>
     2 #include<string.h>
     3 #define Max 1010
     4 int main()
     5 {
     6   int pri[Max];     //pri[i]两个状态 1表示是素数,0表示不是素数,注意,c里面初始化为1不能直接在定义中进行
     7   int dp[Max]={0};      //dp[i]记录长度为 i 的字符串重复字符的最少个数
     8   int a[26];    //26个字符各自出现次数
     9   int mt,ls,i,j,ll;
    10   char mi;
    11   char s[Max],ss[Max];
    12   for(i=0;i<Max;i++)
    13     pri[i]=1;
    14   pri[0]=pri[1]=0;
    15   dp[0]=dp[1]=1;
    16   for(i=2;i<Max;i++)
    17   {
    18     if(pri[i])
    19     {
    20       if(i*2<Max)
    21         dp[i*2]=1;
    22       for(j=2*i;j<Max;j+=i)
    23         pri[j]=0;
    24     }
    25   }
    26   dp[4]=0;    //经过上面的初始化,dp[4]由于2*2也变成了1,但4并没有连接两个素数,所以取消
    27   for(i=2;i<Max;i++)
    28   {
    29     if(pri[i])
    30       dp[i]+=dp[i-1];
    31     else
    32       dp[i]+=dp[i-1]+1;
    33   }
    34   s[0]='0';
    35   while(scanf("%s",s+1)!=EOF)
    36   {
    37     ls=strlen(s);
    38     for(i=0;i<26;i++)
    39       a[i]=0;
    40     for(i=1;i<ls;i++)
    41       a[s[i]-'a']++;
    42     for(mt=0,i=0;i<26;i++)
    43       if(a[i]>mt)
    44       {
    45         mt=a[i];
    46         mi=i+'a';
    47       }
    48     if(mt>=dp[ls-1])
    49     {
    50       printf("YES
    ");
    51       for(ll=0,i=1;i<ls;i++)
    52         if(s[i]!=mi) ss[ll++]=s[i];  //将s中不是出现最多次的字符存起来
    53       for(i=1;i<ls;i++)
    54         if(i>1&&(pri[i]==0||i*2<ls))
    55         {
    56           s[i]=mi;                  //必须是相同字符的位置放上出现次数最多的字符
    57           mt--;                    //放上一个就消耗一个mi
    58         }
    59       for(i=1;i<ls;i++)
    60         if(i<=1||pri[i]&&i*2>=ls)
    61         {
    62           if(mt>0)
    63           {
    64             mt--;                   //将还没完的mi消耗完
    65             s[i]=mi;
    66           }
    67           else
    68           {
    69             s[i]=ss[--ll];          //用其他字符填充空缺
    70           }
    71         }
    72       printf("%s
    ",s+1);
    73     }
    74     else
    75       printf("NO
    ");
    76   }
    77   return 0;
    78 }
    View Code

            

  • 相关阅读:
    gdb 查看变量~p长串末尾省略号, 一个页面显示不完
    Git 在团队中的最佳实践--如何正确使用Git Flow[转]
    apktool+dex2jar+xjad反编译android程序
    浏览器缓存详解:expires,cache-control,last-modified,etag详细说明
    64位windows 7下成功配置TortoiseGit使用Github服务器
    github简单使用教程
    浅淡HTML5移动Web开发
    Surface、SurfaceView、SurfaceHolder及SurfaceHolder.Callback之间的关系
    深入浅出Symfony2
    利用PHP取二进制文件头判断文件类型
  • 原文地址:https://www.cnblogs.com/hchlqlz-oj-mrj/p/4584780.html
Copyright © 2011-2022 走看看