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& ...
随机推荐
- SQL创建数据库、建表、填入内容
--创建数据库 create database Information go --使用数据库 use Information go --创建表 create table Student ( Sno ) ...
- Java泛型理解
Java泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型.当需要使用某一种算法时,又无法具体算法的数据类型,或者想指定类型值的上限或下限,那么这时就需要Java泛型来大显身手 ...
- MATLAB 笔记
MATLAB的学习 Matlab 主要有5大部分构成,分别是MATLAB语言,桌面工具与开发环境,数学函数库 ,图形系统和应用程序接口.以及众多的专业工具.
- 《Learning scikit-learn Machine Learning in Python》chapter1
前言 由于实验原因,准备入坑 python 机器学习,而 python 机器学习常用的包就是 scikit-learn ,准备先了解一下这个工具.在这里搜了有 scikit-learn 关键字的书,找 ...
- python序列成员资格
可以用做登录操作,判断用户名密码是否正确! 代码示例: database = [ ['], ['], ['], ['] ] username = input("UserName: " ...
- php序列化问题
序列化是将变量转换为可保存或传输的字符串的过程:反序列化就是在适当的时候把这个字符串再转化成原来的变量使用.这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性. 1. serialize和 ...
- MYSQL报警:Warning: Using a password on the command line interface can be insecure.
问题描述:执行下面的语句,sql是执行成功了,但是出现了一个报警,报警看上去始终不舒服 mysql -hip -Pport -uuser -ppassword -e "use db;dele ...
- 第一个scrum会议
第一阶段冲刺任务认领: PM薛哥: 让手电筒亮起来 梁哥: 代码测试 康哥: 用户反馈等等
- Alpha冲刺——第五天
Alpha第五天 听说 031502543 周龙荣(队长) 031502615 李家鹏 031502632 伍晨薇 031502637 张柽 031502639 郑秦 1.前言 任务分配是VV.ZQ. ...
- C++ Primer Plus学习:第十五章
第十五章 友元.异常和其他 友元 友元类 表 0-1 class Tv { public: friend class Remote; } Remote类可以使用Tv的数据成员,Remote类在Tv类后 ...