BZOJ3530:[SDOI2014]数数——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=3530
我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串。例如当S=(22,333,0233)时,233是幸运数,2333、20233、3223不是幸运数。
给定N和S,计算不大于N的幸运数个数。
参考:https://www.luogu.org/blog/user17952/solution-p3311
绝对(对我来说)是道难题,尤其是很久不写AC自动机与数位dp的我……
首先n特别大,必须得考虑数位dp。
其次给了一堆串,要求不能出现这些串,先建AC自动机再说。
于是得出了一个愉快的结论:在AC自动机上跑数位dp(写到这里我只想用CaO来表达我的心情)
设$f[i][j][0/1]$为填到$i$数位,当前在AC自动机的$j$节点处,已经小于等于/大于到$i$位的原数。
此时需要注意:为了方便(因为参考是这么写的233),我们正着扫n而非以前的套路倒着扫n,这样做会带来一些问题,于是我们将小于等于也拆开,分别用0和1表示。
(PS:那么反着扫不知道是否可行……以及如果要反着扫的话可能需要反着存串。)
dp式子就不细讲了,直接看代码理解吧。唯一要注意的是不能有前导0所以第一层我们要特殊处理。
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int p=1e9+;
const int L=;
struct AC{
int fail,a[];
bool ed;
}tr[L];
char s[L],s0[L];
int tot,f[L][L][];
void insert(){
int len=strlen(s),now=;
for(int i=;i<len;i++){
int w=s[i]-'';
if(!tr[now].a[w])tr[now].a[w]=++tot;
now=tr[now].a[w];
}
tr[now].ed=;
}
void getfail(){
queue<int>q;
tr[].fail=;
for(int i=;i<;i++){
int u=tr[].a[i];
if(u){
tr[u].fail=;q.push(u);
}
}
while(!q.empty()){
int u=q.front();q.pop();
for(int i=;i<;i++){
if(tr[u].a[i]){
int v=tr[u].a[i];
tr[v].fail=tr[tr[u].fail].a[i];
tr[v].ed|=tr[tr[tr[u].fail].a[i]].ed;
q.push(v);
}else tr[u].a[i]=tr[tr[u].fail].a[i];
}
}
}
inline int add(int x,int y){
x+=y;if(x>=p)x-=p;return x;
}
int main(){
int n,m;
scanf("%s%d",s0,&m);
while(m--){
scanf("%s",s);insert();
}
getfail();
n=strlen(s0);
int ans=;
for(int i=;i<;i++){
int v=tr[].a[i],w=s0[]-'';
if(!tr[v].ed){
if(i<w)f[][v][]++;
else if(i==w)f[][v][]++;
else f[][v][]++;
}
}
for(int i=;i<n;i++){
int w=s0[i]-'';
for(int j=;j<=tot;j++){
if(f[i-][j][]||f[i-][j][]||f[i-][j][])
for(int k=;k<;k++){
int v=tr[j].a[k];
if(tr[v].ed)continue;
if(k<w){
f[i][v][]=add(f[i][v][],add(f[i-][j][],f[i-][j][]));
f[i][v][]=add(f[i][v][],f[i-][j][]);
}else if(k==w){
f[i][v][]=add(f[i][v][],f[i-][j][]);
f[i][v][]=add(f[i][v][],f[i-][j][]);
f[i][v][]=add(f[i][v][],f[i-][j][]);
}else{
f[i][v][]=add(f[i][v][],f[i-][j][]);
f[i][v][]=add(f[i][v][],add(f[i-][j][],f[i-][j][]));
}
}
}
}
for(int i=;i<n;i++){
for(int j=;j<=tot;j++){
ans=add(ans,add(f[i][j][],f[i][j][]));
if(i<n-)ans=add(ans,f[i][j][]);
}
}
printf("%d\n",ans);
return ;
}
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +
+++++++++++++++++++++++++++++++++++++++++++
BZOJ3530:[SDOI2014]数数——题解的更多相关文章
- BZOJ3530: [Sdoi2014]数数
3530: [Sdoi2014]数数 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 322 Solved: 188[Submit][Status] ...
- [bzoj3530][Sdoi2014]数数_AC自动机_数位dp
数数 bzoj-3530 Sdoi-2014 题目大意:给你一个整数集合,求所有不超过n的正整数,是的它的十进制表示下不能再一段等于集合中的任意数. 注释:$1\le n \le 1200$,$1\l ...
- 题解-[SDOI2014]数数
[SDOI2014]数数 这题的前置知识是AC自动机和dp,前置题目是 [JSOI2007]文本生成器,前置题目我写的题解 题解-[JSOI2007]文本生成器.我的讲解假设你做过上面那道题. 这题比 ...
- 【BZOJ3530】数数(AC自动机,动态规划)
[BZOJ3530]数数(AC自动机,动态规划) 题面 BZOJ 题解 很套路的\(AC\)自动机+\(DP\) 首先,如果长度小于\(N\) 就不存在任何限制 直接大力\(DP\) 然后强制限制不能 ...
- 【BZOJ】【3530】【SDOI2014】数数
AC自动机/数位DP orz zyf 好题啊= =同时加深了我对AC自动机(这个应该可以叫Trie图了吧……出边补全!)和数位DP的理解……不过不能自己写出来还真是弱…… /************* ...
- 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)
3530: [Sdoi2014]数数 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 682 Solved: 364 Description 我们称一 ...
- BZOJ 3530: [Sdoi2014]数数 [AC自动机 数位DP]
3530: [Sdoi2014]数数 题意:\(\le N\)的不含模式串的数字有多少个,\(n=|N| \le 1200\) 考虑数位DP 对于长度\(\le n\)的,普通套路DP\(g[i][j ...
- C#版 - Leetcode 633. 平方数之和 - 题解
版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...
- 「SDOI2014」数数 解题报告
「SDOI2014」数数 题目描述 我们称一个正整数 \(N\) 是幸运数,当且仅当它的十进制表示中不包含数字串集合 \(S\) 中任意一个元素作为其子串. 例如当 \(S=(\)22, 333, 0 ...
- 3530: [Sdoi2014]数数
3530: [Sdoi2014]数数 链接 分析: 对给定的串建立AC自动机,然后数位dp.数位dp的过程中,记录当前在AC自动机的哪个点上,保证不能走到出现了给定串的点. 代码: #include& ...
随机推荐
- 修改Qt源码遇到的问题
1.修改源码后用新的Qt版本调试Qt工程,程序直接崩溃:
- HTTP 两种基本请求方法 GET和 POST的区别
GET方法 1.GET交互方式是从服务器上获取数据,而并非修改数据,所以GET交互方式是安全的.就像数据库查询一样,从数据库查询数据,并不会影响数据库的数据信息,对数据库来说,也就是安全的.2.GET ...
- 小白初识 - 基数排序(RadixSort)
基数排序算是桶排序和计数排序的衍生吧,因为基数排序里面会用到这两种其中一种. 基数排序针对的待排序元素是要有高低位之分的,比如单词adobe,activiti,activiti就高于adobe,这个是 ...
- Centos安装Python3(自带pip和setuptools)
安装zlib相关依赖 解决zipimport.ZipImportError: can't decompress data和pip3 ssl证书问题 sudo yum -y install zlib* ...
- [CF1137]Museums Tour
link \(\text{Description:}\) 一个国家有 \(n\) 个城市,\(m\) 条有向道路组成.在这个国家一个星期有 \(d\) 天,每个城市有一个博物馆. 有个旅行团在城市 \ ...
- win7重装系统后设置Python2.7环境
起因 台式机的主板莫名出现问题,显示器画面卡顿不能动,鼠标键盘无反应,在这种情况下只好按住电源键断电.下面重启后,显示器无画面,猜测开机后没有进BIOS.然后就拆机箱,拔下电源线后撬起主板电池几秒再放 ...
- Scrum立会报告+燃尽图(十月十二日总第三次):视频相关工作
此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2190 Scrum立会master:孙赛佳 一.小组介绍 组长:付佳 组员 ...
- 第四次c++作业
一,GitHub地址 https://github.com/ronghuijun/3Elevators-scheduling 二,命令行和文件读写 百度有时候有点蒙,命令行用的是D:>Eleva ...
- lintcode-389-判断数独是否合法
389-判断数独是否合法 请判定一个数独是否有效. 该数独可能只填充了部分数字,其中缺少的数字用 . 表示. 注意事项 一个合法的数独(仅部分填充)并不一定是可解的.我们仅需使填充的空格有效即可. 说 ...
- http://deepdish.io/2015/04/28/creating-lmdb-in-python/
http://deepdish.io/2015/04/28/creating-lmdb-in-python/