BZOJ2532 | CERC2010 Casting Spells

首先跑马拉车。

然后对于每个位置 i 我们求出他的回文对称半径 r_i 。比如说图上假设 i 是回文子串的中心(如果是偶数长度那就是中心的右侧),然后红色位置是子串的右末端,那么 r_i 就是:

然后有了 r_i 之后我们考虑合法的串长什么样子:

于是我们的任务就是找到满足以下条件的 j

  •  j+r_j \geqslant i
  •  j \geqslant i-\frac{r_i}{2}

然后就可以了。那么这里有一个 O(n \log n) 的搞法:从左到右枚举 i ,并同时维护两个集合:一个是当前所有满足条件 [1] 的 j 的位置集合,这个集合以 r_j+j 排序,并记录每个 r_j+j 对应的 j

另一个集合维护所有当前的合法位置 j ,并按照 j 排序。

每次扫到一个 i 只需先清空位置集合所有 r_j+j < ir_j+j 和合法集合对应的 j

然后求合法集合里 i - \frac{r_i}{2} 的后继即可。

 

JLOI2008 CODES

一天半,唉。。真该AFO了。

首先考虑我们可以DP,设状态 dp[i][j] 表示 第 i 个字符串  还需要匹配长度为 j 的前缀   可以得到的最短答案。

转移:

转移就是枚举一个字符串 i_0 来与之匹配。记忆化搜索非常好写。注意讨论两种情况:

  1. i_0比当前前缀长
  2. i_0比当前前缀短

用 dp[i0][?] + 匹配长度 去更新dp[i][j]。(?是因为我懒得讨论了……代码里有)

数据范围很小,暴力匹配即可。

注意事项:

第一个细节就是字符串可以重复利用;

第二个细节是让dp[i][0]=0 其余为 +\infty

第三个细节就是最后统计答案和DP过程中别忘记比较字典序。

字典序:

 answ[i][j] 保存当前 dp[i][j] 对应的具体方案,

更新 dp[i][j] 顺便更新 answ[i][j] 即可。

每次遇到 dp[i0][?]+len  dp[i][j] 相等的情况,判定字典序,然后更新 answ[i][j] 即可。

最后的答案是 dp[i][len[i]]

O(\text{跑得过})

#洛谷 P1066 2^k进制数

题目描述

设r是个2^k 进制数,并满足以下条件:

(1)r至少是个2位的2^k 进制数。

(2)作为2^k 进制数,除最后一位外,r的每一位严格小于它右边相邻的那一位。

(3)将r转换为2进制数q后,则q的总位数不超过w。

在这里,正整数k(1≤k≤9)和w(k<W< span>≤30000)是事先给定的。

问:满足上述条件的不同的r共有多少个?

我们再从另一角度作些解释:设S是长度为w 的01字符串(即字符串S由w个“0”或“1”组成),S对应于上述条件(3)中的q。将S从右起划分为若干个长度为k 的段,每段对应一位2^k进制的数,如果S至少可分成2段,则S所对应的二进制数又可以转换为上述的2^k 进制数r。

例:设k=3,w=7。则r是个八进制数(23=8)。由于w=7,长度为7的01字符串按3位一段分,可分为3段(即1,3,3,左边第一段只有一个二进制位),则满足条件的八进制数有:

2位数:高位为1:6个(即12,13,14,15,16,17),高位为2:5个,…,高位为6:1个(即67)。共6+5+…+1=21个。

3位数:高位只能是1,第2位为2:5个(即123,124,125,126,127),第2位为3:4个,…,第2位为6:1个(即167)。共5+4+…+1=15个。

所以,满足要求的r共有36个。

输入输出格式

输入格式:

输入只有1行,为两个正整数,用一个空格隔开:

k W

输出格式:

输出为1行,是一个正整数,为所求的计算结果,即满足条件的不同的r的个数(用十进制数表示),要求最高位不得为0,各数字之间不得插入数字以外的其他字符(例如空格、换行符、逗号等)。

(提示:作为结果的正整数可能很大,但不会超过200位)

上来给了题解了,好贴心QAQ

第一要用高精度

第二,让你构造一个2k进制的,w/k位的(w的划分残余不考虑)数,且左面一位严格小于右面一位。

我们考虑递推,可以先打一个表

那么设p[i][j]表示从右向左数i位,最高位(最左面)的数最小为j , 可以构成的2k进制数的个数。 (最高位不为0)

那么,有两种转移。一是添加这个最小的数j,那从p[i-1][j+1]转移 (后面i-1位最小取j+1,由此计算可以构成的2k进制数的个数)

二是最高位数字比j大,从p[i][j+1]转移。

那么,看这个

考虑样例k=3 , w=7 的情况,串w肯定不能被完全分割,所以剩下一位,可以取0 ~ 2w%k -1 这样。

那就统计一发答案,最高位取i的时候需要的答案是p[w/k][i+1]这是肯定的。

然后考虑不完全取,ans+= ∑ p[i][1] (2<=i<=w/k)

但是,我们再来考虑这个样例:

k=2,w=8  这四位并不能完全用完。

那么显然最多可以有2k-1位。 (e.g. 当k=2时,位数最多时的方案是123,不存在1234或234或345等等,当k=3时,位数最多时的方案是1234567),也就是说,只需要加一下1~2k-1位的方案p[位数][1]就可以了。

那么就来推一波

然后写一个重载运算符的BNUM类

然后就行了,这是所有代码,注意readint

 

#洛谷 P1026 统计单词个数

垃圾题……照样处理一发区间[i,j]有多少单词然后枚举区间起点i转移就行了。

 

题目描述

给出一个长度不超过200的由小写英文字母组成的字母串(约定;该字串以每行20个字母的方式输入,且保证每行一定为20个)。要求将此字母串分成k份(1<k<=40),且每份中包含的单词个数加起来总数最大(每份中包含的单词可以部分重叠。当选用一个单词之后,其第一个字母不能再用。例如字符串this中可包含this和is,选用this之后就不能包含th)。

单词在给出的一个不超过6个单词的字典中。

要求输出最大的个数。

输入输出格式

输入格式:

每组的第一行有二个正整数(p,k)

p表示字串的行数;

k表示分为k个部分。

接下来的p行,每行均有20个字符。

再接下来有一个正整数s,表示字典中单词个数。(1<=s<=6)

接下来的s行,每行均有一个单词。

输出格式:

一个整数,分别对应每组测试数据的相应结果。

提供一组卡了我好久的数据,注意区间[i,j]的长度。。。

Testdata.in

10 4
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaa
1
aaaaa

Testdata.out

193

比分割字串稍难了一点……主要难在倒推k[i][j] ([i,j]有多少单词),写个模拟就行了吧大概……

 

[洛谷 | 1603] 斯诺登的密码

 

[洛谷 | 1101] 单词方阵

反正代码很难读就对了

题目描述

给一 n \times n 的字母方阵,内可能蕴含多个 yizhong 单词。单词在方阵中是沿着同一方向连续摆放的。摆放可沿着8个方向的任一方向,同一单词摆放时不再改变方向,单词与单词之间可以交叉,因此有可能共用字母。输出时,将不是单词的字母用 * 代替,以突出显示单词。例如:

输入输出格式

输入格式:

第一行输入一个数 n  (7 \leqslant n \leqslant 100)
第二行开始输入 n \times n 的字母矩阵。

输出格式:

突出显示单词的 n \times n 矩阵。

输入输出样例

输入样例#1:

输出样例#1: