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]数数——题解的更多相关文章

  1. BZOJ3530: [Sdoi2014]数数

    3530: [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 322  Solved: 188[Submit][Status] ...

  2. [bzoj3530][Sdoi2014]数数_AC自动机_数位dp

    数数 bzoj-3530 Sdoi-2014 题目大意:给你一个整数集合,求所有不超过n的正整数,是的它的十进制表示下不能再一段等于集合中的任意数. 注释:$1\le n \le 1200$,$1\l ...

  3. 题解-[SDOI2014]数数

    [SDOI2014]数数 这题的前置知识是AC自动机和dp,前置题目是 [JSOI2007]文本生成器,前置题目我写的题解 题解-[JSOI2007]文本生成器.我的讲解假设你做过上面那道题. 这题比 ...

  4. 【BZOJ3530】数数(AC自动机,动态规划)

    [BZOJ3530]数数(AC自动机,动态规划) 题面 BZOJ 题解 很套路的\(AC\)自动机+\(DP\) 首先,如果长度小于\(N\) 就不存在任何限制 直接大力\(DP\) 然后强制限制不能 ...

  5. 【BZOJ】【3530】【SDOI2014】数数

    AC自动机/数位DP orz zyf 好题啊= =同时加深了我对AC自动机(这个应该可以叫Trie图了吧……出边补全!)和数位DP的理解……不过不能自己写出来还真是弱…… /************* ...

  6. 【HDU3530】 [Sdoi2014]数数 (AC自动机+数位DP)

    3530: [Sdoi2014]数数 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 682  Solved: 364 Description 我们称一 ...

  7. BZOJ 3530: [Sdoi2014]数数 [AC自动机 数位DP]

    3530: [Sdoi2014]数数 题意:\(\le N\)的不含模式串的数字有多少个,\(n=|N| \le 1200\) 考虑数位DP 对于长度\(\le n\)的,普通套路DP\(g[i][j ...

  8. C#版 - Leetcode 633. 平方数之和 - 题解

    版权声明: 本文为博主Bravo Yeung(知乎UserName同名)的原创文章,欲转载请先私信获博主允许,转载时请附上网址 http://blog.csdn.net/lzuacm. C#版 - L ...

  9. 「SDOI2014」数数 解题报告

    「SDOI2014」数数 题目描述 我们称一个正整数 \(N\) 是幸运数,当且仅当它的十进制表示中不包含数字串集合 \(S\) 中任意一个元素作为其子串. 例如当 \(S=(\)22, 333, 0 ...

  10. 3530: [Sdoi2014]数数

    3530: [Sdoi2014]数数 链接 分析: 对给定的串建立AC自动机,然后数位dp.数位dp的过程中,记录当前在AC自动机的哪个点上,保证不能走到出现了给定串的点. 代码: #include& ...

随机推荐

  1. jQuery Validate (登录页面相关验证)

    $(function() { var submit = false; var superHtml = []; /** * 匹配企业帐号,以字母开头,长度在6-20之间,只能包含字符.数字和下划线. * ...

  2. 【MYSQL命令】查看日志是否开启及日志过期天数

    show variables like 'log_%';show variables like '%expire_logs_days%'

  3. C#课后小作业

    有关C#基础的练手 跟大家一起分享下 1.让用户输入一个100以内的数 打印1-100之间所有的数,用户输入的数除外 2.让用户输入一个100以内的数 打印1-这个数之间所有的数的和 3.使用一个fo ...

  4. Android开源的精美日历控件,热插拔设计的万能自定义UI

    Android开源的精美日历控件,热插拔设计的万能自定义UI UI框架应该逻辑与界面实现分离,该日历控件使用了热插拔的设计 ,简单几步即可实现你需要的UI效果,热插拔的思想是你提供你的实现,我提供我的 ...

  5. Siki_Unity_2-7_Stealth秘密行动

    Unity 2-7 Stealth秘密行动 Abstract:向量运算:Animation动画:Navigation寻路系统:Mecanim动画系统 任务1&2&3:游戏介绍 & ...

  6. 【转】lvs、nginx、haproxy转发模式优缺点总结

    原文地址: https://yq.aliyun.com/ziliao/78374 一.LVS转发模式 LVS是章文嵩博士写的一个工作于四层的高可能性软件.不像后两者支持七层转发,不过也正因为其简单,所 ...

  7. [network]数字签名

    数字签名(又称公钥数字签名.电子签章)是一种类似写在纸上的普通的物理签名,但是使用了公钥加密领域的技术实现,用于鉴别数字信息的方法.一套数字签名通常定义两种互补的运算,一个用于签名,另一个用于验证. ...

  8. Echarts简单图表

    一.实现要点 常用可视化图表库 Echarts HighCharts D3.js neo4j (NOSQL) 1.导入js库 <script type="text/javascript ...

  9. Dubbo背景和简介

    转载出处 Dubbo开始于电商系统,因此在这里先从电商系统的演变讲起. 单一应用框架(ORM) 当网站流量很小时,只需一个应用,将所有功能如下单支付等都部署在一起,以减少部署节点和成本. 缺点:单一的 ...

  10. Spark Streaming的使用——转载

    转载自   Spark Streaming 使用