Number String

http://acm.hdu.edu.cn/showproblem.php?pid=4055

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Problem Description
The signature of a permutation is a string that is
computed as follows: for each pair of consecutive elements of the permutation,
write down the letter 'I' (increasing) if the second element is greater than the
first one, otherwise write down the letter 'D' (decreasing). For example, the
signature of the permutation {3,1,2,7,4,6,5} is "DIIDID".
Your task is as
follows: You are given a string describing the signature of many possible
permutations, find out how many permutations satisfy this
signature.
Note: For any positive integer n, a permutation of n elements
is a sequence of length n that contains each of the integers 1 through n exactly
once.
 
 
Input
Each test case consists of a string of 1 to 1000
characters long, containing only the letters 'I', 'D' or '?', representing a
permutation signature.
Each test case occupies exactly one single line,
without leading or trailing spaces.
Proceed to the end of file. The '?'
in these strings can be either 'I' or 'D'.
 
 
Output
For each test case, print the number of permutations
satisfying the signature on a single line. In case the result is too large,
print the remainder modulo 1000000007.
 
Sample Input
II
ID
DI
DD
?D
??
 
Sample Output
1
2
2
1
3
6
 
Hint

Permutation {1,2,3} has signature "II".

Permutations {1,3,2} and {2,3,1} have signature "ID".
Permutations {3,1,2} and {2,1,3} have signature "DI".
Permutation {3,2,1} has signature "DD".
"?D" can be either "ID" or "DD".
"??" gives all possible permutations of length 3.
 
 
题意:
给出长为n的一个字符串,根据这个字符串构造长为n+1的数字串
字符为‘I’,下一个数字要比这一个数字大
字符为‘D’ ,下一个数字要比这一个数字小
字符为‘?’,下一个数字没有限制
问数字串有多少种方案
 
一般套路:
f[i][j]表示长为i的串中,最后一个数字为j的方案数
若字符为‘I’,f[i][j]= Σ f[i-1][x]   1 <= x < j     
若字符为‘D’,f[i][j]= Σ f[i-1][x]  j <= x <= i-1  
若字符为‘?’,f[i][j]=Σ f[i-1][x]  1 <= x <= i-1
我们虽然根据 字符保证了相邻两个数字的大小关系,但并没有保证数字串里前i-1个数字没有数字j
这就有了后效性。怎么办?
给状态增加含义:必须选前i-1个数字
我们将过程想象为一个一个填数字的过程
那么由f[i-1][]向f[i][]的转移,就是在末尾(i位置)填上数字i
(因为状态的定义是必须选前i-1个数字)
那么岂不是只能填数字i?字符为‘D’时不就错了吗?第二维不就没有用吗?
我们考虑第二维j(要填的最后一个数字),
我们是否可以将填数字i转换到填数字j,
那么状态转移的时候,就要想如何填j使相邻数字的大小关系不变
将前i-1个数字>=j的都+1,这样就拿出了j,放在最后面
所以,上方状态转移成立
时间复杂度?O(n³) TLE
 
前缀和优化,时间复杂度O(n²)
其实很简单,照着原方程x的取值范围写就行
 1 <= x < j     前缀和就是sum[i-1][j-1]
j <= x <= i-1  前缀和就是 sum[i-1][i-1]-sum[i-1][j-1]
 1 <= x <= i-1  前缀和就是sum[i-1][i-1]
前缀和的更新: sum[i][j]=(sum[i][j-1]+f[i][j])%mod;
 
前缀和优化代码
  1. #include<cstdio>
  2. #include<cstring>
  3. #define mod 1000000007
  4. using namespace std;
  5. int len,f[][],sum[][];
  6. char s[];
  7. int main()
  8. {
  9. while(scanf("%s",s+)!=EOF)
  10. {
  11. memset(f,,sizeof(f));
  12. len=strlen(s+);
  13. f[][]=; sum[][]=;
  14. for(int i=;i<=len+;i++)
  15. for(int j=;j<=i;j++)
  16. {
  17. if(s[i-]=='I') f[i][j]=sum[i-][j-];
  18. else if(s[i-]=='D') f[i][j]=((sum[i-][i-]-sum[i-][j-])%mod+mod)%mod;
  19. else f[i][j]=sum[i-][i-];
  20. sum[i][j]=(sum[i][j-]+f[i][j])%mod;
  21. }
  22. printf("%d\n",sum[len+][len+]);
  23. }
  24. }

未优化代码

  1. #include<cstdio>
  2. #include<cstring>
  3. #define mod 1000000007
  4. using namespace std;
  5. int len,f[][];
  6. char s[];
  7. int main()
  8. {
  9. while(scanf("%s",s+)!=EOF)
  10. {
  11. memset(f,,sizeof(f));
  12. len=strlen(s+);
  13. f[][]=;
  14. for(int i=;i<=len+;i++)
  15. for(int j=;j<=i;j++)
  16. {
  17. if(s[i-]=='I')
  18. for(int k=;k<j;k++) f[i][j]+=f[i-][k];
  19. else if(s[i-]=='D')
  20. for(int k=j;k<i;k++) f[i][j]+=f[i-][k];
  21. else
  22. for(int k=;k<i;k++) f[i][j]+=f[i-][k];
  23. }
  24. int ans=;
  25. for(int i=;i<=len+;i++) ans+=f[len+][i];
  26. printf("%d\n",ans);
  27. }
  28. }

hdu 4055 Number String的更多相关文章

  1. HDU 4055 Number String dp

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4055 Number String Time Limit: 10000/5000 MS (Java/O ...

  2. hdu 4055 Number String(有点思维的DP)

    Number String Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) T ...

  3. hdu 4055 Number String (基础dp)

    Number String Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)To ...

  4. HDU 4055 Number String:前缀和优化dp【增长趋势——处理重复选数】

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4055 题意: 给你一个由'I', 'D', '?'组成的字符串,长度为n,代表了一个1~n+1的排列中 ...

  5. hdu 4055 Number String(dp)

    Problem Description The signature of a permutation is a string that is computed as follows: for each ...

  6. HDU 4055 Number String (计数DP)

    题意:由数字1到n组成的所有排列中,问满足题目所给的n-1个字符的排列有多少个,如果第i字符是‘I’表示排列中的第i-1个数是小于第i个数的. 如果是‘D’,则反之. 析:dp[i][j] 表示前 i ...

  7. HDU 4055 Number String(DP计数)

    题意: 给你一个含n个字符的字符串,字符为'D'时表示小于号,字符为“I”时表示大于号,字符为“?”时表示大小于都可以.比如排列 {3, 1, 2, 7, 4, 6, 5} 表示为字符串 DIIDID ...

  8. hdu 4055 Number String(递推DP)

    给一个只含‘I','D','?'三种字符的字符串,I表示当前数字大于前面的数字,D表示当前的数字小于前面一位的数字,?表示当前位既可以小于又可以大于. 问1~n的排列中有多少个满足该字符串. http ...

  9. HDU 4054 Number String

    HDU 4054 Number String 思路: 状态:dp[i][j]表示以j结尾i的排列 状态转移: 如果s[i - 1]是' I ',那么dp[i][j] = dp[i-1][j-1] + ...

随机推荐

  1. C语言之goto浅析

    1.  读代码时遇了的疑惑点: static int do_bind(const char *host, int port, int protocol, int *family) { int fd; ...

  2. 【第五周】alpha发布之小组评论

    对于昨天的阿尔法发布,有那么几点需要说一下: 1,对这次阿尔法发布的过程,我们组还是基本顺利的,由于之前吃过亏,这次我提前试用了一下投影仪,做了些调试,之后的发布过程起码设备上是正常的. 2,我们的项 ...

  3. 简单的 php 防注入、防跨站 函数

    /** * 简单的 php 防注入.防跨站 函数 * @return String */ function fn_safe($str_string) { //直接剔除 $_arr_dangerChar ...

  4. BZOJ 1853 幸运数字(容斥原理+dfs)

    题意:求闭区间内能被6和8组成的数字整除的数目.n<=1e11. 我们可以预处理出这些6和8组成的数字,大概2500个,然后排除一些如88,66的情况.这样大概还剩下1000个. 转化为[0,r ...

  5. MySQL5.7 初使用

    MySQL 5.7.6 发布了快一年了, 官方的说法是比起前几代有很大的安全性提升,性能报告也是比之前版本提升了 2.3倍. 性能上这么大的提升,安全上也这么大的改进,怎么能不心动呢,这几天出于好奇, ...

  6. 线段树之Sum

    题面: 给定一数列,规定有两种操作,一是修改某个元素,二是求区间的连续和. Input: 输入数据第一行包含两个正整数n,m(n<=100000,m<=500000),以下是m行, 每行有 ...

  7. 【POJ2891】Strange Way to Express Integers(拓展CRT)

    [POJ2891]Strange Way to Express Integers(拓展CRT) 题面 Vjudge 板子题. 题解 拓展\(CRT\)模板题. #include<iostream ...

  8. CF449,急需提高姿势水平

    这可能是我第1场只出1题的div1? A 鬼畜题? 我的dev没有字符统计功能,于是只好扔到notepad++上.数错好几次.题目本身没什么特别的地方. B 当时一直没想出来QAQ 题目中说m> ...

  9. python之快速排序

    快速排序(Quicksort)是对冒泡排序的一种改进. 快速排序由C. A. R. Hoare在1962年提出.它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另 ...

  10. 驱动之DMA的介绍与应用20170210

    本文主要介绍的是DMA相关的知识,首先: 1)在实现DMA传输时,是由DMA控制器直接掌管总线,因此,存在着一个总线控制权转移问题.即DMA传输前,CPU要把 总线控制权交给DMA控制器,而在结束DM ...