题意

  求有多少种 前 \(n\) 个小写字母的排列 \(t\),满足其所有子串按字典序从小到大排列,第 \(k\) 个子串是一个给定字符串 \(s\)。答案模 \(10^9+7\)。

  \(1\le n\le 26\),保证 \(s\) 中仅包含前 \(n\) 个小写字母,且 \(s\) 中的字母两两不同。

  sample input:3 3 b

  sample output:2

题解

  由于排列 \(t\) 的每个字符都互不相同,显然只需要比较首字母就能知道字典序的大小。

  于是确定比 \(s_1\) 小的那些字符的位置即可。

  下面把将字符串 \(s\) 的排名往后挤的名次称为对答案的贡献

  \(O(n)\) 枚举字符串 \(s\) 的位置,然后发现要求 \(s\) 内部比 \(s_1\) 小的字符对答案的贡献,\(O(n)\) 算一下即可。

  设 \(b_i\) 表示第 \(i\) 个小写字母的位置,不难推出一个公式 \((\sum\limits_{i=1}^{s_1-1} (n-b_i+1)) + |s| = k\)

  \(\sum\limits_{i=1}^{s_1-1} (n-b_i+1)\) 表示所有小于 \(s_1\) 的字符对答案的贡献,常数 \(|s|\) 表示字符串 \(s\) 是以 \(s_1\) 开头的所有字符串的第 \(|s|\) 小、

  字符串 \(s\) 中可能已有一些小于 \(s_1\) 的字符,我们把它对应的 \(b_i\) 变成确定的常数。

  我们把所有常数(包括 \(|s|\)、确定的 \(b_i\)、\(n-b_i+1\) 中的 \(n+1\))挪到等号右边,合并为一个常数。那么对于其余在 \(s\) 以外的小于 \(s_1\) 的字符,问题变成 求有多少种方案选择 \(x\) 个未确定的 \(b_i\),使得它们的和为一个常数 \(C\)。

  这是普及组背包问题。设 \(dp(i,j,k)\) 表示前 \(i\) 个未填位置,已经用了 \(j\) 个 \(b_i\),当前总共对答案的贡献是 \(k\) 的方案数。注意 \(k\) 这一维状态是 \(O(n^2)\) 级别的。(这个做法中不确定的 \(b_i\) 数量是不确定的,貌似不能预处理 \(\text{dp}\))

  还要注意一点,排列是有标号的,所以对 \(s\) 以外的部分做背包后,小于 \(s_1\) 的部分和其余部分的方案数要各乘一个阶乘。

  总复杂度 \(O(n^5)\)。应该有个 \(O(n^4)\) 的做法,不过我是鸽子。

#include<bits/stdc++.h>
#define ll long long
#define N 27
#define mod 1000000007
using namespace std;
inline int read(){
int x=0; bool f=1; char c=getchar();
for(;!isdigit(c); c=getchar()) if(c=='-') f=0;
for(; isdigit(c); c=getchar()) x=(x<<3)+(x<<1)+(c^'0');
if(f) return x; return 0-x;
}
int jc[N];
int n,m,len,ans;
char s[N];
namespace Pack{
int x,a[N],dp[N][N*N];
inline void add(int v){a[++x]=v;}
inline void clr(){x=0;}
int solve(int num, int sum){
if(m<0) return 0;
for(int i=0; i<=num; ++i)
for(int j=0; j<=sum; ++j) dp[i][j]=0;
dp[0][0]=1;
for(int i=1; i<=x; ++i)
for(int j=min(num,i); j>=1; --j)
for(int k=sum; k>=a[i]; --k)
dp[j][k] = (dp[j][k] + dp[j-1][k-a[i]]) % mod;
return (ll)dp[num][sum] * jc[num] % mod * jc[x-num] % mod;
}
}using namespace Pack;
int main(){
jc[0]=1; for(int i=1; i<=26; ++i) jc[i]=(ll)jc[i-1]*i%mod;
n=read(), m=read(); scanf("%s",s+1), len=strlen(s+1);
for(int i=1; i<=len; ++i) s[i]-=96;
for(int i=1; i<=n-len+1; ++i){
int sum=m-len, num=s[1]-1;
for(int j=1; j<=len; ++j) if(s[j]<s[1]) sum-=(n-(i-1+j)+1), --num;
for(int j=1; j<i; ++j) add(n-j+1);
for(int j=i+len; j<=n; ++j) add(n-j+1);
ans=(ans+solve(num,sum))%mod;
clr();
}
printf("%d\n",ans);
return 0;
}

【未知来源】K-th String的更多相关文章

  1. Android系统移植与调试之------->如何修改Android系统默认显示【开发者选项】并默认打开【USB调试】和【未知来源】开关

    今天有个用户对[设置]有个特殊的要求,即: 1.开机的时候默认显示[开发者选项]并打开[USB调试]开关    ([Developer options]-->[USB debugging]) 2 ...

  2. mac 上如何安装非app store上的下载的软件-------打开未知来源

    打开了 Terminal 终端后 ,在命令提示后输入 sudo spctl --master-disable 并按下回车执行,如下图所示.   随后再输入当前 Mac 用户的密码,如下图所示.   如 ...

  3. [转帖] IPsec相关知识 --未知来源

    目  录 IPsec IPsec简介 IPsec的协议实现 IPsec基本概念 加密卡 IPsec虚拟隧道接口 使用IPsec保护IPv6路由协议 IKE IKE简介 IKE的安全机制 IKE的交换过 ...

  4. Mac 不显示未知来源选项的解决办法/连接不上网络

    原文来自百度经验: http://jingyan.baidu.com/article/eae078278b37d41fec5485b2.html 灰常感谢原作 关于mac无法连接wifi,我的解决办法 ...

  5. 【未知来源】Randomized Binary Search Tree

    题意 求 \(n\) 个点的 Treap 深度为 \(h=0,1,2,\cdots,n\) 的概率. Treap 是一个随机二叉树,每个节点有权值和优先级,权值和优先级都是 \([0,1]\) 中的随 ...

  6. 安装串口设备驱动时遇到 Windows 无法验证此设备所需的驱动程序的数字签名。最近的硬件或软件更改安装的文件可能未正确签名或已损坏,或者可能是来自未知来源的恶意软件. 问题该如何处理?

    win7 系统直接在 cmd 命令行中输入以下语句,重启电脑后重新安装驱动即可. BCDEDIT -SET LOADOPTIONS DISABLE_INTEGRITY_CHECKS BCDEDIT - ...

  7. 【未知来源】Happy

    题意 给出一个 \(n\) 个节点的树,两点之间有且仅有一条路径相连. 给出 \(m\) 个点对 \(x_i,y_i\),如果添加一条双向边 \((u,v)\) 后 \(x_i\) 和 \(y_i\) ...

  8. [Swift]LeetCode358. 按距离为k隔离重排字符串 $ Rearrange String k Distance Apart

    Given a non-empty string str and an integer k, rearrange the string such that the same characters ar ...

  9. LC 358. Rearrange String k Distance Apart

    Given a non-empty string s and an integer k, rearrange the string such that the same characters are ...

随机推荐

  1. URL encoding(URL编码)

    URL encoding(URL编码),也称作百分号编码(Percent-encoding),是指特定上下文的统一资源定位符(URL)编码机制UrlEncode:将字符串以URL编码返回值:字符串函数 ...

  2. CentOS 7 分区

    必须的分区 boot分区: 作用:引导分区,包含了系统启动的必要内核文件,即使根分区顺坏也能正常引导启动 一般这些文件所占空间在200M以下, 分区建议:分区的时候可选100M-500M之间,如果空间 ...

  3. 【计算机视觉】论文笔记:Ten years of pedestrian detection, what have we learned?

    最近正在研究行人检测,学习了一篇2014年发表在ECCV上的一篇综述性的文章,是对行人检测过去十年的一个回顾,从dataset,main approaches的角度分析了近10年的40多篇论文提出的方 ...

  4. Java程序员的职业发展道路 附:大型网站 -- 架构技能图谱(Java版)

    职业发展道路基本有3条: 第一条路线(技术专精): 初级Java开发---中级--高级---项目主管--Java项目经理---网站架构师----资深专家 第二条路线(技术转产品):初级Java开发-- ...

  5. Apache Zookeeper 集群环境搭建

    Zookeeper 是 一个分布式.开放源码的分布式应用程序协调服务,是Google Chubby的一个开源实现,大多数的分布式应用都需要Zookeeper的支持,这篇文章先简单的和大家分享如何搭建一 ...

  6. volatility 命令

    https://blog.csdn.net/chanyi0040/article/details/100956582 表格 1 Volatility支持的插件列表 插件名称 功能 amcache 查看 ...

  7. 解决应用程序无法正常启动0xc0150002问题(转)

    简述:使用VS2008写了一个MFC程序,结果传到别人的机子上(WIN7)出现应用程序正常初始化(0xc0150002)失败的问题.为什么我的机子上可以,而别人的机子上运行不了呢?下面是我找到的一个解 ...

  8. Vue 中 $attrs 的使用

    名词解释: $attrs--继承所有的父组件属性(除了prop传递的属性.class 和 style ) inheritAttrs:默认值true,继承所有的父组件属性(除props的特定绑定)作为普 ...

  9. sql实现同时向主表和子表插入数据方法

    使用sql语句实现同时向主表和子表插入数据方法: Oracle: -- oracle创建sequence create sequence SEQ_test minvalue 1 maxvalue 99 ...

  10. spark教程(二)-shell操作

    spark 支持 shell 操作 shell 主要用于调试,所以简单介绍用法即可 支持多种语言的 shell 包括 scala shell.python shell.R shell.SQL shel ...