Codeforces 156 C. Cipher
問題
英小文字からなる文字列sが与えられる。
sの任意の連続する二文字に対して、1文字目をアルファベット順で一つ進めて、2文字目を一つ戻す、
または1文字目を一つ戻して、2文字目を一つ進める、
という操作が何度でも行える。
ただし、aの前の文字は存在せず、zの後の文字は存在しないものとする。
sから操作を0回以上繰り返して得られる文字列は(s以外に)いくつあるか、求めよ。
制約条件
文字列の長さ≦100
文字列の個数≦10^4
方針
文字列の各桁の和は、操作仕方によらず、一定である。
また、各桁の和が一定の文字列は、操作によって全て互いに変形することができる。
したがって、長さi文字で、各桁の和がjであるような文字列の個数をdp[i][j]とし、
これを更新するような動的計画法をあらかじめしておけば、
各桁の和と長さから、変形できる文字列の個数が求まることになる。
ソースコード
const int mod = (int)1e9 + 7; int t; int dp[110][110*26]; void run() { dp[0][0]=1; rep(i,105)rep(j,(i+1)*26)if(dp[i][j])rep(k,26)(dp[i+1][j+k]+=dp[i][j])%=mod; cin>>t; rep(i,t){ int a=0; string s; cin>>s; rep(j,s.size())a+=s[j]-'a'; cout<<(dp[s.size()][a]+mod-1)%mod<<endl; } }