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. logstash处理@timestamp时区

    input { stdin { } } filter { #ruby { # code => "event.set('timestamp', event.get('@timestamp ...

  2. 搜索引擎ElasticSearch系列(四): ElasticSearch2.4.4 sql插件安装

    一:ElasticSearch sql插件简介 With this plugin you can query elasticsearch using familiar SQL syntax. You ...

  3. 世界杯足彩怎么买划算?机器学习AI告诉你答案(含预测)

    本文首发于InfoQ公众号头条. 四年一度的世界杯又来了,作为没什么时间看球的码农,跟大家一样,靠买买足彩给自己点看球动力和乐趣, 然而总是买错球队,面对各种赔率也不知道怎么买才划算,足彩是不是碰大运 ...

  4. Scala基础知识笔记1

    上一篇文章介绍了如何下载scala, 因为在官网上点击下载按钮无法下载, 下面介绍scala的基础语法: 1 scala和java的关系 Scala是基于jvm的一门编程语言,Scala的代码最终会经 ...

  5. Linux环境下Java应用性能分析定位-CPU使用篇

    1     CPU热点分析定位背景 CPU资源还是很昂贵的,为了深刻感受到这种昂贵,间下图当前CPU的资源售价: 所以对于程序猿们来说,需要让程序合理高效的使用CPU资源.利用有限的CPU资源来解决完 ...

  6. 第10次Scrum会议(10/22)【欢迎来怼】

    一.小组信息 队名:欢迎来怼小组成员队长:田继平成员:李圆圆,葛美义,王伟东,姜珊,邵朔,冉华小组照片 二.开会信息 时间:2017/10/22 17:20~17:33,总计13min.地点:东北师范 ...

  7. 希尔排序(java实现)

    上篇blog中介绍的直接插入排序,希尔排序就是对直接插入排序的一个优化.比如有这么一种情况:对一个无序数组进行从小到大的排序,但是数组的最后一个位置的数是最小的,我们要把它挪到第一个位置,其他位置的都 ...

  8. ios程序后台继续运行

    1.图标右上角显示消息个数 if ([[UIDevice currentDevice].systemVersion doubleValue] >= 8.0) { UIUserNotificati ...

  9. Beta版冲刺前准备

    [团队概要] 团队项目名:小葵日记 团队名:日不落战队 队员及角色: 队员 角色 备注 安琪 前端工程师 队长 佳莹 前端工程师 智慧 后端工程师 章鹏 后端工程师 语恳 UI设计师 炜坤 前端工程师 ...

  10. 线段树---no end

    额,还有 :区间操作,交,并,补等 区间合并 扫描线 这些问题有空再研究吧.... 先看j2ee了..... 传送门 版权声明:本文为博主原创文章,未经博主允许不得转载.