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\n");
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\n",s+1);
73     }
74     else
75       printf("NO\n");
76   }
77   return 0;
78 }

时间: 2024-10-31 21:06:06

Prime Permutation的相关文章

Prime Permutation(思维好题 )

Prime Permutation codeforces 123A You are given a string s, consisting of small Latin letters. Let's denote the length of the string as |s|. The characters in the string are numbered starting from 1. Your task is to find out if it is possible to rear

Codeforces Beta Round #92 (Div. 1 Only)

A. Prime Permutation 题意:给出一个长为n的字符串,问能否通过重新排列整个字符串,使整个字符串中第i个字符$S_I$与i的素数倍数处的字符$S_prime*i$都相同 关键字:[贪心] 解法:打出1000内的素数表,统计i位和所有prime*i位相同需要的字符数

Project Euler:Problem 70 Totient permutation

Euler's Totient function, φ(n) [sometimes called the phi function], is used to determine the number of positive numbers less than or equal to n which are relatively prime to n. For example, as 1, 2, 4, 5, 7, and 8, are all less than nine and relative

Sicily 1444: Prime Path(BFS)

题意为给出两个四位素数A.B,每次只能对A的某一位数字进行修改,使它成为另一个四位的素数,问最少经过多少操作,能使A变到B.可以直接进行BFS搜索 1 #include<bits/stdc++.h> 2 using namespace std; 3 4 bool isPrime(int n){//素数判断 5 if(n == 2 || n == 3) return true; 6 else{ 7 int k = sqrt(n) + 1; 8 for(int i = 2; i < k; i

HDU 1389 继续畅通工程【最小生成树,Prime算法+Kruskal算法】

继续畅通工程 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 21871    Accepted Submission(s): 9356 Problem Description 省政府"畅通工程"的目标是使全省任何两个村庄间都可以实现公路交通(但不一定有直接的公路相连,只要能间接通过公路可达即可).现得到城镇道路统计表,表中列

HDU 1016 Prime Ring Problem(DFS)

题目链接 Problem Description A ring is compose of n circles as shown in diagram. Put natural number 1, 2, ..., n into each circle separately, and the sum of numbers in two adjacent circles should be a prime. Note: the number of first circle should always

[CareerCup] 7.7 The Number with Only Prime Factors 只有质数因子的数字

7.7 Design an algorithm to find the kth number such that the only prime factors are 3,5, and 7. 这道题跟之前LeetCode的那道Ugly Number II 丑陋数之二基本没有啥区别,具体讲解可参见那篇,代码如下: class Solution { public: int getKthMagicNumber(int k) { vector<int> res(1, 1); int i3 = 0, i

UVA 10200 Prime Time 暴力水题

一个简单的暴力水题,只是输出方式让人无语... #include <stdio.h> #include <string.h> int prime(int n) { int i; for(i=2;i*i<=n;i++) { if((n%i)==0) return 0; } return 1; } int main() { int num[10010]; int i; int a,b; int sum; memset(num,0,sizeof(num)); for(i=0;i&l

POJ 2689 Prime Distance(素数区间筛法--经典题)

大致题意:给定[L,R]区间,找出区间内的每个素数 数据范围 : 1<=L< R<=2,147,483,647) R-L <=1,000,000. R的数值太大,所以不能直接筛[0,R]的,要空间和时间优化,用到区间筛法,另外注意不能用int,因为R和L都是满int的,中间有很多细节处理会爆int的,还要注意1不是素数,所以在区间筛中要特判一下,是个易错的地方 //1160K 16MS C++ 1539B #include<cstdio> #include<ios