Foreign 字串變化 DP

2022-05-20 07:03:02 字數 2418 閱讀 4883

time limit: 10 sec  memory limit: 128 mb

定義乙個(大寫字母)字串集合,初始時值包含乙個給定的字串s1,每次從中任意取出乙個字串,將它變換後再放入集合中。要求新的字串在集合中沒有出現過。

變換的規則:在變化前、後,字串均有大寫字母組成,每次只改動乙個位置,使它的ascll加1。例如:『a』 –> 『b』。如果位置為『z』,則無法改動。

若干次操作後,該集合的元素個數一定會達到最大。

對最後的集合(已按字典序排列)中的si(i >1),定義sj=p[si](si由sj變化而來)。

求最大元素個數及的方案數。(詳情見樣例。)

第1行有1個由大寫字母組成的字串。

輸出2行,每行包含乙個數,第一行表示最大元素個數,第二行表示方案數,答案都模10007。

xyz6

4explain:

最終集合為

方案有,,,

初始字串長度<=1000.

第一問乘一下就好了,這裡討論一下第二問。

'z'-ai得到乙個數字串,那麼操作就變成了:每次將乙個數字-1,最後全部減成0。比如'xyz',我們將其變成'012'

然後考慮狀態是怎麼變來的:

顯然,有幾位是不滿的,就有幾種轉移來的方法(其中任意一位數字+1,即可得到一種父狀態)。

記乙個狀態可以由k個狀態轉移過來,然後答案顯然就是:πk

我們考慮,

我們得到乙個長度為n01串vis,如果這一位是1表示這一位不滿

那麼這個01串對答案的貢獻就是:k ^ (π [vis_i=1]*a_i)。(k表示1的個數

為什麼呢?對於乙個位置,當這一位是[0,ai-1]都是不滿的個數就是ai

然後這樣列舉每一位是否滿,可以做到o(2^n)

我們考慮優化

把k相同的放在一起計算,記貢獻為k^num[k]num[k]即是各種1的個數為k情況的指數之和

num怎麼得到呢?

f[i][j]表示到了第i位,有j個數不滿的方案數,顯然可以得到這樣的遞推式子:

f[i][j] = f[i-1][j] + f[i-1][j-1] * ('z'-a[i])

然後ans = π k^f[n][k],就解決了這題qwq。

1 #include2 #include    

3 #include4 #include5 #include6 #include7 #include8 #include9

using

namespace

std;

10 typedef long

long

s64;

1112

const

int one = 4005;13

const

int mod = 10007;14

15int

n;16

inta[one];

17char

ch[one];

18int

f[one][one];

19int

ans;

2021

intget

()22

3132

int quickpow(int a, int

b)33

41return

res;42}

4344

intmain()

4564

65for(int k=1; k<=n; k++)

66 ans = (s64)ans * quickpow(k, f[n][k]) %mod;

6768 printf("%d"

, ans);

69 }

view code

字串型別的變化

1.format 方法的基本使用 模板字串 format 逗號分隔的引數 模板字串有一系列槽組成,用來控制修改字串中嵌入值出現的位置,其基本思想是將format 方法中逗號分隔的引數按照序號關係替換到模板字串的槽中槽用 表示,如果大括號中沒有序號則按照出現順序替換。如果大括號中指定了使用引數的序號,...

DP 字串變換

給定兩個字串,已知可以使用三種方式進行變換 1.插入乙個字元 2.刪除乙個字元 3.更改乙個字元 請設計乙個演算法,找到兩個字串之間的經歷幾次最小變換,可以字串1轉換成字串2 輸入描述 輸入兩個字串,字串的長度 1000輸出描述 最小變換次數示例1 hello helle1 include usin...

字串dp系列

647.回文子串 給定乙個字串,你的任務是計算這個字串中有多少個回文子串。具有不同開始位置或結束位置的子串,即使是由相同的字元組成,也會被計為是不同的子串。示例 1 輸入 abc 輸出 3 解釋 三個回文子串 a b c 示例 2 輸入 aaa 輸出 6 說明 6個回文子串 a a a aa aa ...