题目

我们称一个正整数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;
}

转载于:https://www.cnblogs.com/Skyminer/p/6782947.html

bzoj 3530: [Sdoi2014]数数 数位dp相关推荐

  1. BZOJ 1662: [Usaco2006 Nov]Round Numbers 圆环数(数位DP+恶心细节)

    BZOJ 1662: [Usaco2006 Nov]Round Numbers 圆环数 Time Limit: 5 Sec  Memory Limit: 64 MB Description 正如你所知 ...

  2. [BZOJ 1026] [SCOI 2009] Windy数 【数位DP】

    题目链接:BZOJ - 1026 题目分析 这道题是一道数位DP的基础题,对于完全不会数位DP的我来说也是难题.. 对于询问 [a,b] 的区间的答案,我们对询问进行差分,求 [0,b] - [0,a ...

  3. bzoj 1026: [SCOI2009]windy数(数位dp)

    1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MB Submit: 7688  Solved: 3470 [Submit][S ...

  4. bzoj 3209 花神的数论题 —— 数位DP

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3209 算是挺简单的数位DP吧,但还是花了好久才弄明白... 又参考了博客:https://b ...

  5. uestc 250 windy数(数位dp)

    题意:不含前导零且相邻两个数字之差至少为2的正整数被称为windy数. windy想知道,在A和B之间,包括A和B,总共有多少个windy数? 思路:数位dp #include<iostream ...

  6. 【2018.4.7】模拟赛之一-ssl2382 K好数【数位dp】

    正题 大意 如果一个数每一位都小于k那么这个数是好数.给出n和k,求1-n里有多少个好数. 解题思路1 将起改为一个k+1进制的数,那么每次加1后这个数都是好数.然后判断一下是否大于n(十进制的情况下 ...

  7. 【BZOJ1026】windy数,数位DP

    Time:2016.08.14 Author:xiaoyimi 转载注明出处谢谢 思路: 依旧蛋疼的数位DP f[i][j]表示有i位,且最高位为j的windy数个数 转移方程比较好写 关键是具体求值 ...

  8. 洛谷2657 windy数(数位DP)

    传送门 [题目分析] 数位DP经典题了. 考虑直接统计R内的windy数和L-1内的windy数,两者相减即为L~R之间的windy数. 考虑DP,记录当前位以及上一位所填的数,当前是否前面为前导零, ...

  9. bzoj3209 花神的数论题——数位dp

    题目大意: 花神的题目是这样的 设 sum(i) 表示 i 的二进制表示中 1 的个数.给出一个正整数 N ,花神要问你 派(Sum(i)),也就是 sum(1)-sum(N) 的乘积. 要对1000 ...

  10. 【CSP201312-4】有趣的数(数位DP)

    problem 问题描述 试题编号: 201312-4 试题名称: 有趣的数 时间限制: 1.0s 内存限制: 256.0MB 问题描述: 问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字 ...

最新文章

  1. HTML5学习笔记二 HTML基础
  2. python tablewidget综合实例_python – 仅通过单击行标题选择QTableWidget行
  3. 【转】Linux中多线程wait使用注意
  4. SAP CRM呼叫中心异步搜索功能的实现
  5. 腾讯第一季度总收入1353亿元 净利润478亿元
  6. 深度学习6-自定义层详解
  7. [2018.07.31 T1] 第一题
  8. python 文本替换 速度_python 实现批量替换文本中的某部分内容
  9. php pager,fleaphp常用方法分页之Pager使用方法
  10. Google最新算法 - 人肉搜索引擎
  11. Windows上使用 OpenOCD 给 STM32 下载程序
  12. 找不到主类或无法加载主类
  13. matlab 双均线,[转载]百年一人的双均线系统及双均线系统公式
  14. WordPress 3.3 –“ Sonny”发布
  15. Ubuntu系统显示实时网速信息
  16. 苹果iCloud服务疑遭中国黑客攻击
  17. 运放的 零点和极点快速找到
  18. 判断手机是否支持google play服务
  19. 快速获取一个网站的所有资源,图片,html,css,js......扒站,仿站必备工具
  20. Pandas学习——Pandas基础

热门文章

  1. php处理post序列化,使用jQuery POST和php序列化和提交表单
  2. 服务器虚拟化嵌套,VMware虚拟机配置嵌套虚拟化
  3. 块裁剪后的矩形边界如何去掉_如何3分钟剪辑出满意的视频号视频?
  4. Hibernate映射组件属性为集合(二)
  5. 【渝粤教育】电大中专电商运营实操 (7)作业 题库
  6. 【Python实例第15讲】分类概率图
  7. phpMyAdmin源码配置过程
  8. 【RLchina第二讲】汪军老师推荐的强化学习理论学习资料
  9. 深入V8引擎-写在前面
  10. [洛谷P3621] [APIO2007] 风铃