数位\(dp\)搞了一上午才搞懂。靠这种傻\(X\)的东西竟然花了我一上午的时间。

数位\(dp\)

概念

数位\(dp\)就是强制你分类一些数,例如给你一段区间,然后让你求出不包含\(2\)的数的个数。

思想

利用前缀和的思想,然后求出区间端点的前缀和这样作差就可以了。

实现方式

有两种实现方式。

记忆化搜索版

这种方法比较好理解(例题不要\(37\))

int dfs(int pos,int pre,int sta,bool limit) {
if (pos==-1) return 1;
if (!limit && dp[pos][sta]!=-1) return dp[pos][sta];
int u = limit?a[pos]:9;
int cnt = 0;
for (int i=0; i<=u; ++i) {
if (i==4 || (pre==3&&i==7)) continue;
cnt += dfs(pos-1,i,i==3,limit&&i==a[pos]);
}
if (!limit) dp[pos][sta] = cnt;
return cnt;
}

查询区间\([0 \ldots n]\)

动态规划版

(例题不要\(62\))

void get_dp()
{
dp[0][0]=1;
for (int i=1;i<10;i++)
{
for (int j=0;j<10;j++)
{
if (j==4) dp[i][j]=0;
else if (j==6)
{
for (int k=0;k<10;k++)
dp[i][j]+=dp[i-1][k];
dp[i][j]-=dp[i-1][2];
}
else
{
for (int k=0;k<10;k++)
dp[i][j]+=dp[i-1][k];
}
}
}
}

查询区间\([0\ldots n)\)

完整代码

动态规划

#include<cstdio>

const int maxn=10;
long long dp[maxn][10]; void get_dp()
{
dp[0][0]=1;
for (int i=1;i<10;i++)
{
for (int j=0;j<10;j++)
{
if (j==4) dp[i][j]=0;
else if (j==6)
{
for (int k=0;k<10;k++)
dp[i][j]+=dp[i-1][k];
dp[i][j]-=dp[i-1][2];
}
else
{
for (int k=0;k<10;k++)
dp[i][j]+=dp[i-1][k];
}
}
}
} int a[maxn];
long long solve(int n)
{
a[0]=0;
while (n)
{
a[++a[0]]=n%10;
n/=10;
}
long long ans=0;
a[a[0]+1]=0;
for (int i=a[0];i>=1;i--)
{
for (int j=0;j<a[i];j++)
if(j!=4 && !(a[i+1]==6 && j==2))
ans+=dp[i][j];
if (a[i]==4) break;
if (a[i+1]==6 && a[i]==2) break;
}
return ans;
} int main()
{
int n,m;
get_dp();
while (scanf("%d %d",&n,&m)==2 && (n||m))
{
long long k1=solve(m+1);
long long k2=solve(n);
printf("%I64d\n",k1-k2);
}
return 0;
}

关于动态规划版有个难点,就是\(solve\)函数里面的两个\(break\)。因为我们枚举的是最高位,所以当我们最高位枚举到不合法数的时候,我们就会固定,那么剩下数的任何数都是不合法的,所以\(break\)

记忆化搜索

#include<cstdio>
#include<iostream>
#include<cstring> using namespace std;
typedef long long LL; int a[20],p;
int dp[20][2]; int dfs(int pos,int pre,bool sta,bool limit) {
if (pos==-1) return 1;
if (!limit && dp[pos][sta]!=-1) return dp[pos][sta];
int u = limit?a[pos]:9;
int cnt = 0;
for (int i=0; i<=u; ++i) {
if (i==4 || (pre==3&&i==7)) continue;
cnt += dfs(pos-1,i,i==3,limit&&i==a[pos]);
}
if (!limit) dp[pos][sta] = cnt;
return cnt;
} int work(int x) {
p = 0;
while (x) {
a[p++] = x%10;
x /= 10;
}
return dfs(p-1,-1,0,true);
} int main() {
memset(dp,-1,sizeof(dp));
int l,r;
cin>>l>>r;
printf("%d",work(r)-work(l-1));
return 0;
}

以上代码借鉴。

数位$dp$的更多相关文章

  1. BZOJ 1911: [Apio2010]特别行动队 [斜率优化DP]

    1911: [Apio2010]特别行动队 Time Limit: 4 Sec  Memory Limit: 64 MBSubmit: 4142  Solved: 1964[Submit][Statu ...

  2. BZOJ 1597: [Usaco2008 Mar]土地购买 [斜率优化DP]

    1597: [Usaco2008 Mar]土地购买 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 4026  Solved: 1473[Submit] ...

  3. Light OJ 1031---Easy Game(区间DP)

    题目链接 http://lightoj.com/volume_showproblem.php?problem=1031 Description You are playing a two player ...

  4. HDU 5807 Keep In Touch DP

    Keep In Touch Problem Description   There are n cities numbered with successive integers from 1 to n ...

  5. 17996 Daily Cool Run (dp)

    时间限制:1000MS  内存限制:65535K 提交次数:0 通过次数:0 题型: 编程题   语言: 不限定 Description Daily Cool Run is a popular gam ...

  6. hdu 1028 Ignatius and the Princess III 简单dp

    题目链接:hdu 1028 Ignatius and the Princess III 题意:对于给定的n,问有多少种组成方式 思路:dp[i][j],i表示要求的数,j表示组成i的最大值,最后答案是 ...

  7. BC.5200.Trees(dp)

    Trees  Accepts: 156  Submissions: 533  Time Limit: 2000/1000 MS (Java/Others)  Memory Limit: 65536/6 ...

  8. hdu 5115 区间dp ***

    题意:有n只狼,每只狼有两种属性,一种攻击力一种附加值,我们没杀一只狼,那么我们受到的伤害值为这只狼的攻击值与它旁边的两只狼的附加值的和,求把所有狼都杀光受到的最小的伤害值. 枚举中间k作为最后杀死的 ...

  9. HDU 4258 Covered Walkway 斜率优化DP

    Covered Walkway Problem Description   Your university wants to build a new walkway, and they want at ...

  10. HDU 3853(期望DP)

    题意: 在一个r*c的网格中行走,在每个点分别有概率向右.向下或停止不动.每一步需要的时间为2,问从左上角走到右下角的期望时间. SOL: 非常水一个DP...(先贴个代码挖个坑 code: /*== ...

随机推荐

  1. CC2540/CC2541 : Set the Peripheral Being Advertising while It is Being Connected

    There is possible to set your CC254X be scanable when it is in connection. But, based on my test,the ...

  2. hdu 5335 Walk Out 搜索+贪心

    Walk Out Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total S ...

  3. 132.try throw catch介绍

    #include <iostream> using namespace std; //try尝试执行,抛出throw,throw之后语句不再执行 //catch处理throw的异常 voi ...

  4. Android官方培训课程中文版(v0.9.7)

    Android官方培训课程中文版(v0.9.7) Google Android团队在2012年的时候开设了Android Training板块 - http://developer.android.c ...

  5. vue+Element实现tree树形数据展示

    组件: Element(地址:http://element.eleme.io/#/zh-CN/component/tree):Tree树形控件 <el-tree ref="expand ...

  6. 修复EJBInvokerServlet漏洞

    1600/invoker/EJBInvokerServlet(存在命令执行) 修复方案: # 删除接口 # 设置中间件的访问控制权限,禁止web访问 /invoker 目录 http://www.cn ...

  7. [转] CentOS 7 为firewalld添加开放端口及相关资料

    转自http://www.cnblogs.com/hubing/p/6058932.html 1.运行.停止.禁用firewalld 启动:# systemctl start  firewalld 查 ...

  8. 50个极好的bootstrap框架

    转自:http://sudasuta.com/bootstrap-admin-templates.html  https://www.cnblogs.com/sanhao/p/9184323.html ...

  9. 路飞学城Python-Day9(practise)

    def save(): with open('practise_4', 'w+', encoding='utf-8') as f: for i in user_list: info = str(i) ...

  10. IE9 下的ajax缓存问题的处理

      使用jQuery的getJSON从后台定时获取数据并刷新界面,使用以下方法时,在Chrome,Firefox下没问题,但在IE9下却无法刷新数据 1 2 3 4 5 $.getJSON(webAp ...