codeforces 156C Cipher 组合数学 字符串dp
2015-09-08 19:59
309 查看
链接:http://codeforces.com/problemset/problem/156/C
题意:
给定一个字符串,有两种操作。1)选一个位置Sp, 将Sp的字母往后一位(例如a->b),Sp+1的字母往前一位。2)选一个位置Sp, 将Sp的字母往前一位(例如a->b),Sp+1的字母往后一位。(z没有后一位,a没有前一位)
定义两个字符串一致意味着由一个字符串进行n次这种操作后可以变到另一个字符串(n>=0)
要求除了这个给定的字符串之外有多少与其一致的字符串,将数量取模(109+ 7)(10^9+ 7)
思路:
感觉这种题真的没怎么见到过。。第一次做还真没有想出思路。。。要好好反思下为什么。。
对于每一个操作都可以看到,对前一个位置所做的操作,与对后一个所做的操作是相反的。再进一步,对于每一个字符都有一个对应的ascii码,而每个操作就是对前一个字符的ascii码 +1 或者 -1 ,并对后一个字符进行相反的操作。那么应该要想到对于每一个字符串来说,与之一致的字符串就意味着他们每一位的ascii码加起来的总和是固定的。
那么就可以进行dp的状态转移了,每个字符串都可以由比其少一位的字符串对应的ascii码值转移过来。
定义dp[i][j]dp[i][j]为长度为i的ascii码的和为j 的字符串的个数。并且将a的值设为起始值 为 0
状态转移方程:dp[i][j+k]+=dp[i−1][j]dp[i][j+k] += dp[i-1][j] (0 <= k < 26)
注意还要先动态打一个表出来,不然会超时哦。一个表的计算量必定小于100*100*26*26,直接秒出。
反思:
这道题的思路不算难,为什么自己没有想到?首先,觉得自己对于问题的抽象能力还是太弱,没有看到问题的本质,就拿这题的操作来说,做的时候一味的关注了具体的操作,内在的联系没有想到,对于计算机里这个操作意味着什么,没有思考到。没能将看似无关的东西联系起来。具体这题来说就是感觉对于每一个字符没有转换成数值来看待,过于关注字符本身。其次,对于dp的感觉确实是有点弱,还是要加强。。
以后做题思考的时候应该多思考事物内在的联系,不要总是关注表面的东西,当陷入困境时,要努力跳出来,看看之间的联系或者转换成更加抽象的东西。抽象的来看问题这也是coder的必备技能之一吧。果然还是太弱了。。要加油啊~
题意:
给定一个字符串,有两种操作。1)选一个位置Sp, 将Sp的字母往后一位(例如a->b),Sp+1的字母往前一位。2)选一个位置Sp, 将Sp的字母往前一位(例如a->b),Sp+1的字母往后一位。(z没有后一位,a没有前一位)
定义两个字符串一致意味着由一个字符串进行n次这种操作后可以变到另一个字符串(n>=0)
要求除了这个给定的字符串之外有多少与其一致的字符串,将数量取模(109+ 7)(10^9+ 7)
思路:
感觉这种题真的没怎么见到过。。第一次做还真没有想出思路。。。要好好反思下为什么。。
对于每一个操作都可以看到,对前一个位置所做的操作,与对后一个所做的操作是相反的。再进一步,对于每一个字符都有一个对应的ascii码,而每个操作就是对前一个字符的ascii码 +1 或者 -1 ,并对后一个字符进行相反的操作。那么应该要想到对于每一个字符串来说,与之一致的字符串就意味着他们每一位的ascii码加起来的总和是固定的。
那么就可以进行dp的状态转移了,每个字符串都可以由比其少一位的字符串对应的ascii码值转移过来。
定义dp[i][j]dp[i][j]为长度为i的ascii码的和为j 的字符串的个数。并且将a的值设为起始值 为 0
状态转移方程:dp[i][j+k]+=dp[i−1][j]dp[i][j+k] += dp[i-1][j] (0 <= k < 26)
注意还要先动态打一个表出来,不然会超时哦。一个表的计算量必定小于100*100*26*26,直接秒出。
反思:
这道题的思路不算难,为什么自己没有想到?首先,觉得自己对于问题的抽象能力还是太弱,没有看到问题的本质,就拿这题的操作来说,做的时候一味的关注了具体的操作,内在的联系没有想到,对于计算机里这个操作意味着什么,没有思考到。没能将看似无关的东西联系起来。具体这题来说就是感觉对于每一个字符没有转换成数值来看待,过于关注字符本身。其次,对于dp的感觉确实是有点弱,还是要加强。。
以后做题思考的时候应该多思考事物内在的联系,不要总是关注表面的东西,当陷入困境时,要努力跳出来,看看之间的联系或者转换成更加抽象的东西。抽象的来看问题这也是coder的必备技能之一吧。果然还是太弱了。。要加油啊~
[code]#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> using namespace std; #define M 2709 #define mod 1000000007 int ans; int dp[M][M]; char s[M]; void slove() { dp[0][0] = 1; for(int i = 1;i <= 100;i++) { for(int j = 0;j <= (i-1)*26;j++) 遍历i-1位的所有可能和 { for(int k = 0;k < 26;k++)//在当前位加a~z dp[i][j+k] = (dp[i][j+k]+dp[i-1][j])%mod; } } } int main() { int t; scanf("%d",&t); slove(); while(t--) { scanf("%s",s); int n = strlen(s); int sum = 0; for(int i = 0;i < n;i++) { sum += s[i]-'a'; } printf("%d\n",dp [sum]-1); } return 0; }
相关文章推荐
- android四大组件(Activity,Service,BroadcastReceiver,Content Provider)
- c#生成动态库并加载
- 使用apache benchmark(ab) 测试报错汇总
- c prime plus 第十二章
- POJ 1149:PIGS 网络流经典题
- objc的runtime
- table 中超出单元格内容使用省略号表示
- POJ 1149:PIGS 网络流经典题
- python 日期, 文件, 代码片段
- Spring Boot Logback应用日志
- javascript中array类型的重排序方法
- 1020. 月饼 (25)
- String类的使用
- Android 事件处理
- Spring Boot Logback应用日志
- Spring Boot Logback应用日志
- Spring Boot Logback应用日志
- 如何有效降低内存峰值防止过高及其原理分析
- I/O流之--转换流:InputStreamReader 和InputStreamWriter
- js获取url中文乱码问题解决方案