随便记录几个题, 防止连数位dp的思路都忘了,2333
数位dp
- 先将上限各位保存到num数组
- 从高位到低位dfs(暴力)
- 记忆化,优雅的暴力,否则就是O(n)的算法了,对单个数据也有很大的加速
- pos为-1时以及记忆存在时可直接返回
- 关键:时刻记住判断条件,做到不重不漏
HDU 3652 B-number
B-number
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 10029 Accepted Submission(s): 6011
Problem Description
A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string “13” and can be divided by 13. For example, 130 and 2613 are wqb-numbers, but 143 and 2639 are not. Your task is to calculate how many wqb-numbers from 1 to n for a given integer n.
Input
Process till EOF. In each line, there is one positive integer n(1 <= n <= 1000000000).
Output
Print each answer in a single line.
Sample Input
13
100
200
1000
Sample Output
1
1
2
2
题意:找到1~n内能被13整除且包含13的整数的个数。
思路:记忆化,正常dfs,体会很好。
#include "bits/stdc++.h"
using namespace std;
int n;
int num[12];
int dp[12][10][13][2]; //位置,前导,mod13,达到上限
int dfs(int pos, int pre, bool han13, int mod13, bool f) {
if(pos==-1) return han13&&!mod13;
if(!f&&dp[pos][pre][mod13][han13]!=-1) return dp[pos][pre][mod13][han13];
int up=f?num[pos]:9;
int cnt=0;
for(int i=0; i<=up; ++i) {
int mod=(mod13*10+i)%13;
if(han13||pre*10+i==13) cnt+=dfs(pos-1,i,true,mod,f&&i==up);
else cnt+=dfs(pos-1,i,false,mod,f&&i==up);
}
if(!f) dp[pos][pre][mod13][han13]=cnt;
return cnt;
}
int main() {
ios::sync_with_stdio(false);
memset(dp,-1,sizeof(dp));
while(cin>>n) {
int now=0;
while(n) {
num[now++]=n%10;
n/=10;
}
cout<
HDU 3709 Balanced Number
据说是经典题目,一开始想着让支点左边的力矩等于右边的力矩,然后发现要枚举好多东西,不好操作;
看了题解发现自己像个SD,直接枚举支点不就好了吗?
同时也发现自己头脑逐渐呆滞。
Balanced Number
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 9191 Accepted Submission(s): 4377
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 with pivot fixed at 3. The torqueses are 42 + 11 = 9 and 9*1 = 9, for left part and right part, respectively. It’s your job
to calculate the number of balanced numbers in a given range [x, y].
Input
The input contains multiple test cases. The first line is the total number of cases T (0 < T ≤ 30). For each case, there are two integers separated by a space in a line, x and y. (0 ≤ x ≤ y ≤ 1018).
Output
For each case, print the number of balanced numbers in the range [x, y] in a line.
Sample Input
2
0 9
7604 24324
Sample Output
10
897
#include "bits/stdc++.h"
using namespace std;
typedef long long ll;
ll x, y, nx, ny;
int num[20], p;
ll dp[20][20][4000]; // 数位,pivot(支点),sum的取值(防止负值,加了2000,但是别人的没加也AC了)
void go(ll a) {
p=0;
while(a) {
num[p++]=a%10;
a/=10;
}
}
ll dfs(int pos, int pivot, int sum, int f) {
if(pos<0) return !sum;
if(!f&&dp[pos][pivot][2000-sum]!=-1) return dp[pos][pivot][2000-sum];
ll cnt=0;
int up=f?num[pos]:9; //若x-1<0,则此处up<0,下方循环不会进入
for(int i=0; i<=up; ++i) {
int newsum=sum+(pos-pivot)*i;
cnt+=dfs(pos-1,pivot,newsum,f&&i==up);
}
if(!f) dp[pos][pivot][2000-sum]=cnt;
return cnt;
}
int main() {
ios::sync_with_stdio(false);
memset(dp,-1,sizeof(dp));
int T;
cin>>T;
while(T--) {
cin>>x>>y;
go(x-1); // 不用担心x-1<0,原因见上方注释
nx=0;
for(int i=0; i
HDU 3886 Final Kichiku “Lanlanshu”
这题很烦!!!
先把我自己的代码放这,WA掉的,应该是算重复了,但不知道是哪里,思路跟题解有些差别。
//#include "bits/stdc++.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include