数位DP之小小结
资料链接:http://wenku.baidu.com/view/9de41d51168884868662d623.html
http://wenku.baidu.com/view/d2414ffe04a1b0717fd5dda8.html
几位大大的数位BLOG:http://www.cnblogs.com/jackge/archive/2013/05/15/3080958.html
http://www.cnblogs.com/kuangbin/category/476047.html
CXLOVE:http://blog.csdn.net/acm_cxlove/article/details/7819907
给出数位DP的DFS记忆化DP模板;
因为原理比较简单,不用去构造方程,而且简洁。。
ll dfs(int pos,int cet,int sum,int flag){
if (sum<) return ;
if (pos<=) return sum==;
if (!flag&&dp[pos][cet][sum]!=-) return dp[pos][cet][sum];
int end=flag?a[pos]:;
ll ret=;
for (int i=;i<=end;i++)
ret+=dfs(pos-,cet,sum+i*(pos-cet),flag&&(end==i));
if (!flag) dp[pos][cet][sum]=ret;
return ret;
}
复杂度是DP方程的状态数,DP设计的好坏与DP的状态数有关。。
FLAG表示是否在边界,当不再边界时我们可以做无关后面数的操作,否则,要考虑后面的数对前面有没有影响。。
我做的几道题:
HDU 3652:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<iostream>
using namespace std;
int a[];
int len;
int dp[][][][]; int dfs(int pos,int sum,int res,int last,int flag)
{
if (pos<) return res&&(sum==);
if (!flag&&dp[pos][sum][res][last]!=-) return dp[pos][sum][res][last];
int end=flag?a[pos]:;
int ret=;
for (int i=;i<=end;i++)
ret+=dfs(pos-,(sum*+i)%,res||(last==&&i==),i,flag&&i==end);
if (!flag) dp[pos][sum][res][last]=ret;
return ret;
} int get(int x)
{
len=;
while (x){
a[len++]=x%;
x/=;
}
return dfs(len-,,,,);
} int main()
{
int n;
memset(dp,-,sizeof(dp));
while (scanf("%d",&n)!=EOF)
{
printf("%d\n",get(n));
}
}
HDU 3555:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<iostream>
using namespace std;
typedef long long ll;
int a[];
int len;
ll dp[][][]; ll dfs(int pos,int res,int last,int flag)
{
if (pos<) return res;
if (!flag&&dp[pos][res][last]!=-) return dp[pos][res][last];
int end=flag?a[pos]:;
ll ret=;
for (int i=;i<=end;i++)
ret+=dfs(pos-,res||(last==&&i==),i,flag&&i==end);
if (!flag) dp[pos][res][last]=ret;
return ret;
} ll get(ll x)
{
len=;
while (x){
a[len++]=x%;
x/=;
}
return dfs(len-,,,);
} int main()
{
ll n;
int T;
scanf("%d",&T);
memset(dp,-,sizeof(dp));
while (T--)
{
scanf("%I64d",&n);
printf("%I64d\n",get(n));
}
}
HDU 4389:有打表方法;每个100000个数打表,再统计;
数位DP代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
typedef long long ll;
#define mod 2520
int inx[];
ll dp[][][];
int a[];
using namespace std; void init(){
int num=;
for (int i=;i<=mod;i++)
if (mod%i==) inx[i]=++num;
} int gcd(int a,int b){
if (a%b==) return b;
return gcd(b,a%b);
} int lcm(int a,int b){
return a*b/gcd(a,b);
} ll dfs(int pos,int slcm,int sum,int flag){
if (pos<) return sum%slcm==;
if (!flag&&dp[pos][inx[slcm]][sum]!=-) return dp[pos][inx[slcm]][sum];
int end=flag?a[pos]:;
ll ret=;
for (int i=;i<=end;i++){
int nowlcm=slcm;
int nowsum=(sum*+i) %mod;
if (i) nowlcm=lcm(nowlcm,i);
ret+=dfs(pos-,nowlcm,nowsum,flag&&i==end);
}
if (!flag) dp[pos][inx[slcm]][sum]=ret;
return ret;
} ll get(ll x)
{
int pos=;
while (x)
{
a[pos++]=x%;
x/=;
}
return dfs(pos-,,,);
} int main(){
int T;
scanf("%d",&T);
memset(dp,-,sizeof(dp));
init();
while (T--){
ll a,b;
scanf("%I64d%I64d",&a,&b);
printf("%I64d\n",get(b)-get(a-));
}
return ;
}
这里我们不可能保存每个值去除以其数位的和,我们可以枚举数位的和,然后DFS能满足的数的个数,再看其数能不能整除其数位。
数位和的状态是1-81。。。;
HDU 4334 :
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<string.h>
#include<algorithm> using namespace std;
int bit[];
int dp[][]; int dfs(int t,int num,int flag)
{
if (t==) return num>=;
if (num<) return ;
if (!flag&&dp[num][t]!=-) return dp[num][t];
int ans=;
int end=flag?bit[t]:;
for (int i=;i<=end;i++)
ans+=dfs(t-,num-i*(<<(t-)),flag&&i==end);
if (!flag) dp[num][t]=ans;
return ans;
}
int main()
{
int T;
scanf("%d",&T);
memset(dp,-,sizeof(dp));
for (int i=;i<=T;i++)
{
int a,b;
scanf("%d%d",&a,&b);
int t=;
int ans=;
while (a)
{
ans+=a%*(<<t);
t++;
a/=;
}
int len=;
while (b)
{
bit[++len]=b%;
b/=;
}
printf("Case #%d: %d\n",i,dfs(len,ans,));
}
return ;
}
前面的做了差不多,这也是简单题了,先预处理F[A],然后处理。。
codeforces 55D: http://codeforces.com/problemset/problem/55/D
比较麻烦的题;求一个范围的书能被其数位整除的个数。
切题点:1-9的公倍数为2520;
我们可以定义方程DP[POS][LCM][SUM]表示:处理第POS位,其数位的最小公倍数数多少,该数MOD2520是多少,但是有个问题会爆内存,
要开DP[20][2520][2520];
解决办法是:2520=2^3*3^2*5*7
y于是又4*3*2*2= 48中组合。。
我们可以对LCM用下标代替,就不会爆内存了。。。真是奇妙的方法。。
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
typedef long long ll;
#define mod 2520
int inx[];
ll dp[][][];
int a[];
using namespace std; void init(){
int num=;
for (int i=;i<=mod;i++)
if (mod%i==) inx[i]=++num;
} int gcd(int a,int b){
if (a%b==) return b;
return gcd(b,a%b);
} int lcm(int a,int b){
return a*b/gcd(a,b);
} ll dfs(int pos,int slcm,int sum,int flag){
if (pos<) return sum%slcm==;
if (!flag&&dp[pos][inx[slcm]][sum]!=-) return dp[pos][inx[slcm]][sum];
int end=flag?a[pos]:;
ll ret=;
for (int i=;i<=end;i++){
int nowlcm=slcm;
int nowsum=(sum*+i) %mod;
if (i) nowlcm=lcm(nowlcm,i);
ret+=dfs(pos-,nowlcm,nowsum,flag&&i==end);
}
if (!flag) dp[pos][inx[slcm]][sum]=ret;
return ret;
} ll get(ll x)
{
int pos=;
while (x)
{
a[pos++]=x%;
x/=;
}
return dfs(pos-,,,);
} int main(){
int T;
scanf("%d",&T);
memset(dp,-,sizeof(dp));
init();
while (T--){
ll a,b;
scanf("%I64d%I64d",&a,&b);
printf("%I64d\n",get(b)-get(a-));
}
return ;
}
OJ挂了,现在也没评测出来。。
求一个范围[L,R]数中1的总数。。
方程想到就是超级大水题;
#include<stdio.h>
#include<iostream>
#include<string.h>
#include<cmath>
typedef long long ll;
int a[];
ll dp[][];
using namespace std; ll dfs(int pos,int num,int flag)
{
if (pos<) return num;
if (!flag&&dp[pos][num]!=-) return dp[pos][num];
int end=flag?a[pos]:;
ll ret=;
for (int i=;i<=end;i++)
if (i==) ret+=dfs(pos-,num+,flag&&end==i);
else ret+=dfs(pos-,num,flag&&end==i);
if (!flag) dp[pos][num]=ret;
return ret;
} ll get(ll x)
{
int pos=;
while (x){
a[pos++]=x%;
x/=;
}
return dfs(pos,,);
} int main()
{
ll a,b;
memset(dp,-,sizeof(dp));
while (scanf("%lld%lld",&a,&b)!=EOF){
printf("%lld\n",get(b)-get(a-));
}
return ;
}
还有好多好多各种状态的数位DP题,果然太弱切不动。。
数位DP之小小结的更多相关文章
- 数位DP复习小结
转载请注明原文地址http://www.cnblogs.com/LadyLex/p/8490222.html 之前学数位dp的时候底子没打扎实 虚的要死 这次正好有时间……刷了刷之前没做的题目 感觉自 ...
- hdu 3709 数字dp(小思)
http://acm.hdu.edu.cn/showproblem.php?pid=3709 Problem Description A balanced number is a non-negati ...
- 牛客寒假算法基础集训营3处女座和小姐姐(三) (数位dp)
链接:https://ac.nowcoder.com/acm/contest/329/G来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言52428 ...
- 处女座和小姐姐(三)(数位dp)
链接:https://ac.nowcoder.com/acm/contest/329/G 来源:牛客网 题目描述 经过了选号和漫长的等待,处女座终于拿到了给小姐姐定制的手环,小姐姐看到以后直呼666! ...
- [bzoj3209][花神的数论题] (数位dp+费马小定理)
Description 背景众所周知,花神多年来凭借无边的神力狂虐各大 OJ.OI.CF.TC …… 当然也包括 CH 啦.描述话说花神这天又来讲课了.课后照例有超级难的神题啦…… 我等蒟蒻又遭殃了. ...
- P2188 小Z的 k 紧凑数 题解(数位DP)
题目链接 小Z的 k 紧凑数 解题思路 数位DP,把每一个数位的每一个数对应的可能性表示出来,然后求\(num(1,r)-num(1,l-1)\),其中\(num(i,j)\)表示\([i,j]\)区 ...
- 数位dp小练
最近刷题的同时还得填填坑,说来你们也不信,我还不会数位dp. 照例推几篇博客: 数位DP讲解 数位dp 的简单入门 这两篇博客讲的都很好,不过代码推荐记搜的形式,不仅易于理解,还短. 数位dp的式子一 ...
- 数位dp小结
数位dp其实就是一种用来求区间[l, r]满足条件的数的个数.数位是指:个十百千万,而在这里的dp其实相当于暴力枚举每一位数. 我们通过把l, r的每位数分解出来,然后分别求r里满足条件的数有多少,l ...
- 牛客训练三:处女座和小姐姐(三)(数位dp)
题目链接:传送门 思路:数位dp的记忆化搜索模板 从高位向低位枚举,逐位确定每一位的6的个数,dp[i][s]表示处理到第i条边,状态为s时的数字的个数. 注意,要使用long long类型. #in ...
随机推荐
- 用VBA计算WPS 表格ET EXCEL中的行数和列数的多重方法
用VBA计算WPS 表格ET EXCEL中的行数和列数 每种方法中上面的是Excel的行数,下面的是Excel的列数. 方法1: ActiveSheet.UsedRange.Rows.Count Ac ...
- SSM框架
1.http://www.cnblogs.com/verlen11/p/5349747.html 2.Mybatis http://www.cnblogs.com/xdp-gacl/p/4261895 ...
- MHA命令系统介绍 --masterha_master_switch
常用参数介绍 --master_state=dead 强制的参数,参数值为"dead" 或者 "alive" . 如果 设置为 alive 模式,masterh ...
- 第十六章 调试及安全性(In .net4.5) 之 调试程序
1. 概述 本章内容包括 如何选择合适的构建类型.创建和管理编译指令.管理程序数据文件(pdb)和指令. 2. 主要内容 2.1 构建类型 .net中默认的两种生成模式是 发布(Release)模式 ...
- python Django 学习笔记(一)—— Django安装
注:本人python版本2.7.5 ,win7系统 安装Django https://www.djangoproject.com/download/ 官方下载Django-1.5.5.tar.gz 1 ...
- 使用eclipse开发
Eclipse下载地址:http://www.eclipse.org/ 下载后进行解压缩,点击eclipse.exe即可使用eclipse workspace:工作区 Project:项目 ...
- Java当中的异常
异常:中断了正常指令流的事件,是JVM虚拟机产生的对象 异常是程序运行时产生的,和编译无关 class Test{ public static void main(String args[]){ Sy ...
- Sqlserver中char,nchar,varchar与Nvarchar的区别分析
1. char类型: 对英文(ASCII)字符占用1个字节,对一个汉字占用2个字节,CHAR存储定长数据很方便,CHAR字段上的索引效率极高,比如定义char(10),那么不论你存储的数据是否达 到了 ...
- DrawerLayout带有侧滑功能的布局类(1)
DrawerLayout: DrawerLayout顾名思义就是一个管理布局的.使用方式可以与其它的布局类类似. DrawerLayout带有滑动的功能.只要按照drawerLayout的规定布局方式 ...
- hdu 5326 Work
题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5326 Work Description It’s an interesting experience ...