bzoj 3530: [Sdoi2014]数数 数位dp
题目
我们称一个正整数N是幸运数,当且仅当它的十进制表示中不包含数字串集合S中任意一个元素作为其子串。例如当S=(22,333,0233)时,233是幸运数,2333、20233、3223不是幸运数。
给定N和S,计算不大于N的幸运数个数。
题解
有一道scoi2013的数数比这道题丧病多了...
这道题还是比较好做的。
给定范围的时给定了n的长度,并且要求计算数的个数。
所以可以基本确定这是一道数位dp了。
然后又要求有一部分串不能出现
这是经典的在AC自动机上的dp了.
所以我们需要在拿到的数不超过n的情况下在AC自动机上dp.
可以这么设定状态:
\(f[i][j]\)表示从高位向低位逐个确定了\(n\)位,走到了自动机的节点\(j\)
但是要求我们找出来的串的大小不得超过\(n\),所以我们现在的状态无法支持转移.
原因就在于我们没有办法确定下一位取值的范围,可能是\([0,a_i]\),也可能是\([0,9]\)
所以需要多加一维的状态表示我们前面的数字是不是顶到顶了.
所谓顶到顶的意思就是下一位只能取\([0,a_i]\)范围内的数.
所以我们两维状态交替更新即可.细节看代码.
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
inline void read(int &x){
x=0;static char ch;bool flag = false;
while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
}
#define rg register int
#define rep(i,a,b) for(rg i=(a);i<=(b);++i)
#define per(i,a,b) for(rg i=(a);i>=(b);--i)
const int maxn = 2048;
const int mod = 1e9+7;
int ch[maxn][10],nodecnt,fail[maxn],q[maxn],l,r;
bool danger[maxn];
inline void insert(char *s){
int nw = 0;
for(rg i=0,c;s[i];++i){
c = s[i] - '0';
if(ch[nw][c] == 0) ch[nw][c] = ++ nodecnt;
nw = ch[nw][c];
}danger[nw] = true;
}
void build(){
l = 0;r = -1;
rep(c,0,9){
if(ch[0][c] != 0){
fail[ch[0][c]] = 0;
q[++r] = ch[0][c];
}
}
while(l <= r){
int u = q[l++];
rep(c,0,9){
int t = ch[fail[u]][c];
if(ch[u][c] == 0) ch[u][c] = t;
else{
danger[ch[u][c]] |= danger[t];
fail[ch[u][c]] = t;
q[++r] = ch[u][c];
}
}
}
}
char num[maxn],s[maxn];
int f[maxn][maxn][2],a[maxn];
int main(){
scanf("%s",num+1);
int n = strlen(num+1);
rep(i,1,n) a[i] = num[i] - '0';
int m;read(m);
while(m--){
scanf("%s",s);
insert(s);
}build();
rep(i,1,a[1]) if(!danger[ch[0][i]]){
f[1][ch[0][i]][i == a[1]] += 1;
}
rep(i,1,n-1) rep(j,0,nodecnt){
if(f[i][j][1]){
rep(k,0,a[i+1]){
if(danger[ch[j][k]]) continue;
f[i+1][ch[j][k]][k == a[i+1]] += f[i][j][1];
if(f[i+1][ch[j][k]][k == a[i+1]]>=mod)f[i+1][ch[j][k]][k == a[i]] -= mod;
}
}
if(f[i][j][0]){
rep(k,0,9){
if(danger[ch[j][k]]) continue;
f[i+1][ch[j][k]][0] += f[i][j][0];
if(f[i+1][ch[j][k]][0] >= mod) f[i+1][ch[j][k]][0] -= mod;
}
}
}
ll ans = 0;
rep(i,0,nodecnt){
ans += f[n][i][0] + f[n][i][1];
if(ans >= mod) ans -= mod;
}
memset(f,0,sizeof f);
rep(i,1,9) if(!danger[ch[0][i]]) f[1][ch[0][i]][0] += 1;
rep(i,1,n-2) rep(j,0,nodecnt){
if(f[i][j][0]){
rep(k,0,9){
if(danger[ch[j][k]]) continue;
f[i+1][ch[j][k]][0] += f[i][j][0];
if(f[i+1][ch[j][k]][0] >= mod) f[i+1][ch[j][k]][0] -= mod;
}
}
}
rep(i,1,n-1){
rep(j,0,nodecnt){
ans += f[i][j][0];
if(ans >= mod) ans -= mod;
}
}
printf("%lld\n",ans);
return 0;
}
bzoj 3530: [Sdoi2014]数数 数位dp的更多相关文章
- BZOJ_1662_[Usaco2006 Nov]Round Numbers 圆环数_数位DP
BZOJ_1662_[Usaco2006 Nov]Round Numbers 圆环数_数位DP Description 正如你所知,奶牛们没有手指以至于不能玩“石头剪刀布”来任意地决定例如谁先挤奶的顺 ...
- BZOJ_1026_[SCOI2009]windy数_数位DP
BZOJ_1026_[SCOI2009]windy数_数位DP 题意:windy定义了一种windy数.不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道, 在A和B之 ...
- BZOJ 3530: [Sdoi2014]数数 [AC自动机 数位DP]
3530: [Sdoi2014]数数 题意:\(\le N\)的不含模式串的数字有多少个,\(n=|N| \le 1200\) 考虑数位DP 对于长度\(\le n\)的,普通套路DP\(g[i][j ...
- BZOJ 3530 [SDOI2014]数数 (Trie图/AC自动机+数位DP)
题目大意:略 裸的AC自动机+数位DP吧... 定义f[i][x][0/1]表示已经匹配到了第i位,当前位置是x,0表示没到上限,1到上限,此时数是数量 然而会出现虚拟前导零,即前几位没有数字的情况, ...
- [BZOJ 3530] [Sdoi2014] 数数 【AC自动机+DP】
题目链接:BZOJ - 3530 题目分析 明显是 AC自动机+DP,外加数位统计. WZY 神犇出的良心省选题,然而去年我太弱..比现在还要弱得多.. 其实现在做这道题,我自己也没想出完整解法.. ...
- [BZOJ 1026] [SCOI 2009] Windy数 【数位DP】
题目链接:BZOJ - 1026 题目分析 这道题是一道数位DP的基础题,对于完全不会数位DP的我来说也是难题.. 对于询问 [a,b] 的区间的答案,我们对询问进行差分,求 [0,b] - [0,a ...
- [bzoj 1026]windy数(数位DP)
题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1026 分析: 简单的数位DP啦 f[i][j]表示数字有i位,最高位的数值为j的windy数总 ...
- bzoj 1026 [SCOI2009]windy数(数位DP)
1026: [SCOI2009]windy数 Time Limit: 1 Sec Memory Limit: 162 MBSubmit: 4550 Solved: 2039[Submit][Sta ...
- BZOJ 3209 花神的数论题 数位DP+数论
题目大意:令Sum(i)为i在二进制下1的个数 求∏(1<=i<=n)Sum(i) 一道非常easy的数位DP 首先我们打表打出组合数 然后利用数位DP统计出二进制下1的个数为x的数的数量 ...
随机推荐
- http => https 升级
准备证书 阿里云安全(云盾)-> CA证书服务,购买证书,个人测试的话可以使用免费的,期限1年. 购买证书后,把域名与证书进行绑定,提交审核,大概10分钟左右,正常情况下审核就可以通过.证书准备 ...
- Go 学习笔记
官网: https://golang.org/ 环境: $GOROOT: GOROOT环境变量指定了Go的安装目录. $GOPATH: GOPATH 环境变量指定workspace的目录. 命令行: ...
- 算法调参 weight_ratio, weight_seqratio
from openpyxl import Workbook import xlrd import time import Levenshtein as Le target_city_list = [' ...
- 【python】-- try except (异常捕获)、断言
try except (异常捕获) 当程序出错了,但是我们又不想让用户看到这个错误,而且我在写程序的时候已经预料到了它可以出现这样的错误,出现这样的错误代表着什么,我们可以提前捕获这些个错误 1.异常 ...
- css position: relative,absolute具体解释
关于CSS中 position在布局中非常重要,查了非常多资料都说的非常难理解.以下说说个人的理解: 语法: position: relative | absolute relative: 对象遵循常 ...
- CentOS7.x 报错 There are no enabled repos.
地址 :http://mirrors.163.com/centos/7/os/x86_64/Packages/ wget http://mirrors.163.com/centos/7/os/x8 ...
- 好用的 curl 抓取 页面的封装函数
由于经常使用php curl 抓取页面的内容,在此mark 平时自己封装的 curl函数,(其实 现在也开始用 Python 来爬了~ ^-^) /** * 封装curl方法 * @author Fr ...
- js格式化货币金额
/* 格式化金额, s : 金额 n : 保留位数 */ function formatMoney(s, n) { n = n > 0 && n <= 20 ? n : 2 ...
- 关于date和String互相转换的问题
其实原理很简单,就是将String类型的变量使用SimpleDateFormat来转换成Date,然后用getTime()方法比较 SimpleDateFormat sdf = new SimpleD ...
- nginx服务
nginx服务 一.nginx安装 1.yum安装:yum -y install nginx 注:centos 7中yum安装nginx前需要先安装 epel-release 2.源码包安装 安装之 ...