数位dp

r HDU - 3709 Balanced Numbe(数位dp解析)

删除回忆录丶 提交于 2020-02-09 15:34:01
题目链接 : https://vjudge.net/contest/355127#problem/C Problem Description A balanced number is a non-negative integer that can be balanced if a pivot is placed at some digit. More specifically, imagine each digit as a box with weight indicated by the digit. When a pivot is placed at some digit of the number, the distance from a digit to the pivot is the offset between it and the pivot. Then the torques of left part and right part can be calculated. It is balanced if they are the same. A balanced number must be balanced with the pivot at some of its digits. For example, 4139 is a balanced number

寒假Day20:数位dp

左心房为你撑大大i 提交于 2020-02-05 00:07:43
数位dp:在数位上做动态规划 Bomb HDU - 3555 求含49的数字个数(49连号)。 不要62 HDU - 2089 给出a、b两个区间,求所有不含有4或62(62连号)的数字的个数。 AC代码: 1 #include<string.h> 2 #include<iostream> 3 #include<stdio.h> 4 #include<algorithm> 5 #include<queue> 6 #include<vector> 7 #include<map> 8 #include<cmath> 9 using namespace std; 10 #define inf 0x3f3f3f3f 11 const int N=50; 12 typedef long long ll; 13 14 int digit[25]; 15 ll dp[N][2]; 16 17 ll dfs(int len,bool if6,bool limit) 18 { 19 if(len==0) 20 return 1; 21 if(limit==0&&dp[len][if6]) 22 return dp[len][if6]; 23 ll cnt=0,up; 24 if(limit==1) 25 up=digit[len]; 26 else 27 up=9; 28 for(int i=0;

不要62(数位dp模板题)

寵の児 提交于 2020-02-01 21:20:59
AC_Code: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <string> 5 #include <cmath> 6 #include <queue> 7 #include <stack> 8 #include <vector> 9 #include <set> 10 #include <map> 11 #include <algorithm> 12 using namespace std; 13 typedef long long ll; 14 const int maxn=10; 15 16 int dp[maxn][maxn][2]; 17 int a[maxn]; 18 int len; 19 20 int dfs(int pos, int pre, int status, bool lead, bool limit){ 21 if( pos<1 ) return status; 22 if((!limit)&&(!lead)&&dp[pos][pre][status]!=-1) return dp[pos][pre][status]; 23 int up=limit?a[pos]:9; 24 int ans=0; 25 for(int i=0;i<=up;i++){

SR的学习日志_DP问题_数位DP

眉间皱痕 提交于 2020-02-01 19:28:48
今天来学习简单的数位DP问题的解法。 数位DP一般会给你两个数L和R,两个都很大,没法直接用int类型存储的那种大。 一道典型例题是:给出两个数L和R,求区间[L, R]里不含62或4的数有几个。 这道题如果直接从L到R遍历一遍的话基本上是超时了。因此,我们可以 创建一个数组 ans[i][j] , i 表示数位为 i 时, 以 j 开头的数里符合要求的数量。如ans[2][3]的话,就表示有两位数时,开头为3的数里符合要求的数量,ans[2][3]有9个,分别是 20,21,22,23,25,26,27,28,29。 所以,状态转移方程为: 那这个ans数组有什么用呢?假如我们有一个函数f(x), f(x)表示从0到x的数里面符合要求的个数,那么我们 求区间[L, R]里符合要求的数量可以转化为求f(L-1)和f( R )的值 。 而利用上面的ans数组,我们就可以轻松地求出f(L-1)和f( R )了。 具体代码如下: /** * TODO Auther: by SR * Date: 2020-01-29 10:42:55 * LastEditTime: 2020-01-29 17:40:32 * ! 今日运势: 吉,无bug * 数位DP **/ # include <iostream> # include <cmath> # include <algorithm> #

LUOGU P6034 Ryoku与最初之人笔记 简要题解

馋奶兔 提交于 2020-01-31 23:12:05
比赛的时候有个地方忘记取模怒砍80,调了一下午Orz(虽然我总共貌似就打这个比赛半个多小时 我们一眼看到涉及到公约数/同余 和 xor,所以我们想到了一些关于xor的性质 a+b >= a xor b >= b-a (b>a),而且ab不相等所以就是求a xor b = b - a的数对数 但是我们看到n<=1e18,这玩意怎么求??? 我们从异或的性质入手 发现a xor b = b - a的充要条件就是a & b = b 也就是我们考虑a,b作为两个二进制集合,则a是b的真子集 然后我们发现就是求Σ2^popcount(i)-1,这个好像是数位DP的套路, 但是我怎么会数位DP 于是我找了一波规律 i     0 1 2 3 4 5 6 7 pop   0 1 1 2 1 2 2 3 value  0 1 1 3 1 3 3 7 发现这个数列是个类似分形的东西,每次把pop复制到后面再整体+1,然后我就觉得可以搞 这个玩意又像倍增又像二分又像分治(但是又啥都不像 (其实像格雷码 我们预处理出前(1<<k)个数的贡献和,然后用一个变量cnt来记录此前的popcount,我们发现cnt对答案的贡献是可以暴力计算的,于是就做完了(雾 这个玩意虽然写了一堆 但是思路肥肠好想 我好像写的不是正解,因为他们算贡献直接用子集的子集就给整出来了 时间复杂度O(log^2 N) 代码:

和与或 数位dp

不羁岁月 提交于 2020-01-26 17:02:00
   链接: https://ac.nowcoder.com/acm/problem/21336 来源:牛客网 给你一个数组R,包含N个元素,求有多少满足条件的序列A使得 0 ≤ A[i] ≤ R[i] A[0]+A[1]+...+A[N-1]=A[0] or A[1]... or A[N-1] 输出答案对1e9+9取模 第一行输入一个整数N (2 ≤ N ≤ 10) 第二行输入N个整数 R[i] (1 ≤ R[i] ≤ 1e18) #include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=1e7+1000; const ll mod=1e9+9; ll a[20],dp[100][2000]; int n; ll dfs(ll d,int st) { if(d<0) return 1; ll ans=dp[d][st]; if(ans!=-1) return ans; int temp=st; for(int i=0;i<n;i++) if(a[i]>>d&1) temp|=1<<i; ans=dfs(d-1,temp); for(int i=0;i<n;i++) { if(st>>i&1) ans=(ans+dfs(d-1,temp))%mod; else if(a[i]>>d

ACWING311. 月之谜(数位DP)

无人久伴 提交于 2020-01-21 12:30:51
如果一个十进制数能够被它的各位数字之和整除,则称这个数为“月之数”。 给定整数L和R,你需要计算闭区间[L,R]中有多少个“月之数”。 输入格式 输入占一行,包含两个整数L和R。 输出格式 输出一个整数,表示月之数的个数。 数据范围 1≤L,R<231 输入样例: 1 100 输出样例: 33 思路: 如果记录的是数字大小和数字位总和,最后再来比较,那么就不能实现记忆化(相当于每个数字都判断一遍) 实际的数字位和不大,可以枚举这个数字位和。 # include <cstdio> # include <cstring> # include <algorithm> using namespace std ; int MOD ; int digit [ 20 ] ; int dp [ 12 ] [ 205 ] [ 205 ] ; int dfs ( int len , int mod , int sum , int limit ) { if ( len == 0 ) { if ( mod == 0 && sum == MOD ) return 1 ; else return 0 ; } if ( ! limit && dp [ len ] [ mod ] [ sum ] != - 1 ) return dp [ len ] [ mod ] [ sum ] ; int up = limit

XHXJ's LIS HDU - 4352(LIS,数位dp)

好久不见. 提交于 2020-01-21 12:27:31
#define xhxj (Xin Hang senior sister(学姐)) If you do not know xhxj, then carefully reading the entire description is very important. As the strongest fighting force in UESTC, xhxj grew up in Jintang, a border town of Chengdu. Like many god cattles, xhxj has a legendary life: 2010.04, had not yet begun to learn the algorithm, xhxj won the second prize in the university contest. And in this fall, xhxj got one gold medal and one silver medal of regional contest. In the next year’s summer, xhxj was invited to Beijing to attend the astar onsite. A few months later, xhxj got two gold medals and was

数位dp (2)

有些话、适合烂在心里 提交于 2020-01-19 23:48:16
今天继续写几个数位dp F - Balanced Number 题目大意:给你一个区间,让你求这个区间之中满足条件的数字有多少。 这个条件:可以选数的一个位为轴,左右到轴的长度乘上那个数字本身相等的数有多少? 我的思路:首先我们要研究这个题目的数字要求,就是找到一个点然后去枚举每一个点是轴,然后我们就再dfs里面搜索 因为我们要求点到轴的力矩,但是我们又不知道力矩的位置,所以我们用一个数来记录到此位置的力矩 这个怎么记录呢?比如说数字abcdef 第一次就是a,第二次是a*2+b 第三次是a*3+b*2+c。。。。 所以我们需要有一个来记录这个力矩,还需要有一个数来记录 a a+b a+b+c.... 这个时候就很好求了。 所以这个dp我是这么定义的 dp[i][j][k][h]表示到第 i 位 轴为 j 力矩为 k 数字之和为 h 但是自己敲了之后发现有问题 首先就是这个数组开的太大了,其次就是这个状态定义的唯一不唯一很难确定。 我对于这个dp数组是真的无奈,不知道该怎么去定义,有时候定义多了,有时候定义少了。 状态是不是唯一真的很难去判断。 看了题解,题解是这么定义的, dp[i][j][k] 表示第 i 为以第 j 位 是否满足条件,满足k==0,不满足k!=0 这个状态一定义下来,就很好写这个dp了。 !!注意最后要减去全为0 的数,0 00 000 0000 000000

数位DP

…衆ロ難τιáo~ 提交于 2020-01-18 14:54:02
数位DP 用HDU的一道题目作为实例 不要62 ,这道题是不带前导零的一道实例。 # include <bits/stdc++.h> using namespace std ; int dp [ 20 ] [ 2 ] ; int a [ 20 ] ; int dfs ( int pos , int pre , int state , bool limit ) { if ( pos == - 1 ) return 1 ; if ( ! limit && dp [ pos ] [ state ] != - 1 ) return dp [ pos ] [ state ] ; int up = limit ? a [ pos ] : 9 ; int ans = 0 ; for ( int i = 0 ; i <= up ; ++ i ) { if ( pre == 6 && i == 2 ) continue ; if ( i == 4 ) continue ; ans + = dfs ( pos - 1 , i , i == 6 , limit && i == a [ pos ] ) ; } if ( ! limit ) dp [ pos ] [ state ] = ans ; return ans ; } int solve ( int x ) { int pos = 0 ;