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的数的数量 ...
随机推荐
- Sitemesh3的使用心得
项目中用到了sitemesh3,就把使用心得记下来,至于配置之类的,官方网站都有,这里只是写下自己对它的理解,方便再次理解, sitemesh是基于过滤器的原理,拦截到符合配置文件中配置的路径,然后会 ...
- [转]Html position(static、relative、absolute、fixed)
转自:http://blog.csdn.net/topviewers/article/details/21644305 讲解不错,转载备忘. position的四个属性值: 1.relative2.a ...
- SecureCRT的Home+End+Del键映射
在securecrt界面:工具 → 键映射编辑器,在弹出的键盘中: 1.点击“home”,会弹出一个窗口,在“发送字符串”中输入:\033[1~ 2.点击“end”,会弹出一个窗口,在“发送字符串”中 ...
- ajax (异步js+xml)
AJAX 基础 AJAX = 异步js+xml 通过与后台服务器进行少量数据交换,实现前台网页局部更新 XMLHttpRequest对象 是 AJAX 的基础 var xmlhttp; if (win ...
- 创建第一个SpringBoot的demo程序
在这里,我只介绍手动创建的其中一种方式. 默认,你已经安装了IntelliJ IDEA和JDK1.8,如果没有,请先安装. 第一步:选择新建一个项目 File-->New-->Proj ...
- 打开或者 关闭 php 的错误报告
一般线上的环境,我会 php的报错信息屏蔽掉,php.ini 设置的办法 如下: display_errors = Off error_reporting = E_ALL 在代码中,可以这样~~: e ...
- 【thrift】初识thrift
Reference:http://www.ibm.com/developerworks/cn/java/j-lo-apachethrift/ http://jacksongblack.blog.51c ...
- Android app与PC端交互
app提交信息到PC端mysql数据库 新建名为SignActivity package com.example.administrator.success; import android.app.A ...
- php输入输出
php是服务器脚本语言,js是客户端脚本语言 php用表单接收数据,echo 输出数据,$定义变量. <?php echo $_POST["sub"]; // POST后是表 ...
- Cache-Control常用类型
可缓存性 no-cache 强制所有缓存了此响应的缓存用户,在使用已存储的缓存数据前,发送条件请求到原始服务器,若未过期,则使用缓存数据,否则重新获取 no-store 不存储有关客户端请求或服务器响 ...