数位dp

poj 3252 Round Numbers 数位dp

核能气质少年 提交于 2020-01-03 10:14:57
题目链接 找一个范围内二进制中0的个数大于等于1的个数的数的数量。基础的数位dp 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define mem1(a) memset(a, -1, sizeof(a)) 4 int digit[50], dp[50][50][50], len; 5 int dfs(int len, int num0, int num1, int f, int first) { //first记录前面是否全部为0 6 if(!len) { 7 return num0>=num1; 8 } 9 if(!f&&!first&&dp[len][num0][num1]!=-1) 10 return dp[len][num0][num1]; 11 int ret = 0, maxx = f?digit[len]:1; 12 for(int i = 0; i<=maxx; i++) { 13 if(i == 0) { 14 ret += dfs(len-1, first?0:num0+1, num1, f&&i==maxx, first); 15 } else { 16 ret += dfs(len-1, num0, num1+1, f&&i==maxx, 0); 17 } 18 } 19 if(!f&&!first

poj 3252 Round Numbers(数位dp)

…衆ロ難τιáo~ 提交于 2020-01-03 10:14:49
Round Numbers Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 11681 Accepted: 4392 Description The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, Paper, Stone' (also known as 'Rock, Paper, Scissors', 'Ro, Sham, Bo', and a host of other names) in order to make arbitrary decisions such as who gets to be milked first. They can't even flip a coin because it's so hard to toss using hooves. They have thus resorted to "round number" matching. The first cow picks an integer less than two billion. The second cow does the same. If the numbers are both

POJ 3252 Round Numbers(数位DP)

落爺英雄遲暮 提交于 2020-01-03 10:14:39
Round Numbers Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 6983 Accepted: 2384 Description The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, Paper, Stone' (also known as 'Rock, Paper, Scissors', 'Ro, Sham, Bo', and a host of other names) in order to make arbitrary decisions such as who gets to be milked first. They can't even flip a coin because it's so hard to toss using hooves. They have thus resorted to "round number" matching. The first cow picks an integer less than two billion. The second cow does the same. If the numbers are both "round

数位dp

那年仲夏 提交于 2019-12-28 14:23:33
不要62 学习于 数位dp总结 之 从入门到模板 里面的介绍中dfs函数有一个pre参数,可以省略。 题目的要求就是一个范围内的数不含4和62的数的个数,两道基础题。 # include <stdio.h> # include <string.h> int a [ 20 ] , dp [ 20 ] [ 2 ] ; int dfs ( int pos , int sta , int flag ) { //分别存的第几位,上一位是否是6,是否达到上界 if ( pos == - 1 ) return 1 ; if ( ! flag && dp [ pos ] [ sta ] != - 1 ) return dp [ pos ] [ sta ] ; int up = flag ? a [ pos ] : 9 ; //没达到上界就可以从0到9,达到上界他就是不完整的 int i , sum = 0 ; for ( i = 0 ; i <= up ; i ++ ) { if ( i != 4 && ! ( sta && i == 2 ) ) sum + = dfs ( pos - 1 , i == 6 , flag && i == a [ pos ] ) ; } if ( ! flag ) dp [ pos ] [ sta ] = sum ; //没达到上界才可记录 return sum ;

P2657 [SCOI2009]windy数 - 数位DP

倖福魔咒の 提交于 2019-12-25 18:24:35
只需要相邻两个位置差大于等于2即可 那么对于一个数,我只需要知道他的最高位,以及这个数有多少位(防止超过边界),就可以表示出这个状态了 设f[i][j]表示满足“前i位中最高位的值为j”的windy数有多少个 虽然说不能包含前导0,但是j可以为0吧,比如一个数10234,里面有个0 首先处理出那些不需要考虑边界,显然比给定数小的windy数,这个很好统计 接着考虑到一些靠近给定数x的windy数,为了不超出x数,需要逐个“ 试填 ”数字 试填是这种题的核心,先确认前面几位,让还未确定的数的范围一步步减小 比如13579,先确认最高位为1,然后从第二位开始,从0~2试一下能否和1绝对值之差大于等于2 因为是从0~3-1,所以试填的数一定比给定数小(10xxx,12xxx一定小于13xxx) 然后再确认第二位为3,枚举第三位0~5-1 在这个过程中,需要保证已经确定的位也需要满足题意,对于一个数12345,若已经确认了前两位为12,那么往后也无法构成windy数了,直接退出 一直到最后,如果到最后一个数也没有退出,则说明给定数x本身也是windy数,答案加1就好了 #include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace

windy 数(还是数位dp

为君一笑 提交于 2019-12-24 00:03:43
windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道, 在A和B之间,包括A和B,总共有多少个windy数? Input   包含两个整数,A B。 Output   一个整数 Sample Input 【输入样例一】 1 10 【输入样例二】 25 50 Sample Output 【输出样例一】 9 【输出样例二】 20 Hint 【数据规模和约定】 100%的数据,满足 1 <= A <= B <= 2000000000 。 借此题讲一下数位dp的几个关键; 0,注意构造dp的转移方程,这也是题目的突破口 1,数据是否前后包括 ( 100%的数据: solve(m+1)-(n) ); 2,注意数位判断的顺序,(x00000以下的个数->x00000~xy0000的个数->xy0000~xyz000的个数......: for(int i=len;i>0;i--)for(int j=0;j<a[i];j++)) 3,根据题目首位是否需要特判(此题条件相邻二数差至少为2,故首位没有前导零与之相差,需要特判:即清加所有小于x00000的数) 4,特变注意数位改变节点的判断,如无必要,之后的都无需判断(if(abs(a[i]-a[i+1])<2)break;) #include<cstdio> #include

[题解]windy数(数位dp

旧街凉风 提交于 2019-12-24 00:03:22
简单数位dp 数位dp最重要的还是要理解模板的原理,理解数位dp的原理,理解题目的做法,套模板不一定能解决所有问题,反而大概率会有一些细节出错而无法想到 #include<bits/stdc++.h> #define ll long long using namespace std; int a,b,num[11],len; int f[11][11]; int dfs(int pos,bool lmt,bool led,int lst){ if(pos==0)return 1; if(!lmt && !led && f[pos][lst]!=-1)return f[pos][lst]; int top=lmt?num[pos]:9; int ans=0; // ans+=dfs(pos-1,lst==num[pos],led,lst); // if(lst+1<=num[pos])ans+=dfs(pos-1,(lst+1==num[pos]),0,lst+1); // if(lst-1>=0)ans+=dfs(pos-1,0,(led && lst-1),lst-1); for(int i=0;i<=top;i++){ if(abs(i-lst)<2)continue; ans+=dfs(pos-1,lmt && i==num[pos],(led && !i),(led&&!i

D - windy数 (数位DP)

人走茶凉 提交于 2019-12-24 00:03:03
D - windy数 windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道, 在A和B之间,包括A和B,总共有多少个windy数? 题解:用dp[i][j]表示对前i位,在第i+1位为j时的windy数 代码解释: /***********************************************/ int a[20]; ll dp[20][11];//记录前i位中windy数个数 //因为前一位j为多少对后面的枚举是有影响的 ll dfs(int cur,int pre,bool limit,bool lead) { //lead用于判断从高位到低位枚举时有没有前导0, //如对1232 //当前面几位枚举的都是0时,后面一位的枚举是不受前面一位限制的, //因为如果前面几位都是0,就相当于前几位是不存在的, //所以才有: if( abs(i-pre) >=2 || lead) //这就是枚举条件 if(cur==0) return 1; if(!limit && dp[cur][pre]!=-1 && pre>0) return dp[cur][pre]; // pre>0 ,如果pre==0,涉及到位数,需要再次循环 ll ans=0; int cu=limit?a[cur]:9; for(int

windy数(数位DP)

情到浓时终转凉″ 提交于 2019-12-24 00:02:43
windy数 Crawling in process... Crawling failed Time Limit: 1000MS Memory Limit: 165888KB 64bit IO Format: %lld & %llu Submit Status Description Input Output Sample Input Sample Output Hint Description   windy定义了一种windy数。不含前导零且相邻两个数字之差至少为2的正整数被称为windy数。 windy想知道, 在A和B之间,包括A和B,总共有多少个windy数? Input   包含两个整数,A B。 Output   一个整数 Sample Input 【输入样例一】 1 10 【输入样例二】 25 50 Sample Output 【输出样例一】 9 【输出样例二】 20 Hint 【数据规模和约定】 100%的数据,满足 1 <= A <= B <= 2000000000 。 /* 题解用的递推,自己用DFS枚举一遍过了,成就感^0^ */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> #define mod 2520 using namespace

HDU 2089 不要62 (数位DP)

一世执手 提交于 2019-12-22 15:18:31
题意 求区间[L,R]内含有4或者含有相邻62的数的个数。 思路 和上一道题目 HDU 3555 一样,只需要改变一下状态转移即可。 第一道自己独立写出来的数位DP,而且还1Y~~^_^ 代码 [cpp] #include <iostream> #include <cstdio> #include <cmath> #include <algorithm> #include <string> #include <cstring> #include <vector> #include <set> #include <stack> #include <queue> #define MID(x,y) ((x+y)/2) #define MEM(a,b) memset(a,b,sizeof(a)) #define REP(i, begin, m) for (int i = begin; i < begin+m; i ++) using namespace std; typedef long long LL; typedef vector <int> VI; typedef set <int> SETI; typedef queue <int> QI; typedef stack <int> SI; const int oo = 0x7fffffff; const int maxn = 10;