数位dp (2)
今天继续写几个数位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 这些数是一样的,都是0,重复计算了很多次。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <algorithm>
#include <vector>
#include <iostream>
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
const int maxn = ;
const int mod = ;
typedef long long ll;
ll dp[][][];
int a[maxn]; ll dfs(int pos,int sta,int num,bool limit)
{
if (pos == -) return num == ;
if (num < ) return ;
if (!limit&&dp[pos][sta][num] != -) return dp[pos][sta][num];
int up = limit ? a[pos] : ;
ll ans = ;
for(int i=;i<=up;i++)
{
ans += dfs(pos - , sta, num + (pos - sta)*i, limit && (i == up));
}
if (!limit) dp[pos][sta][num] = ans;
return ans;
} ll solve(ll x)
{
if (x < ) return ;
int pos = ;
while(x)
{
a[pos++] = x % ;
x /= ;
}
ll ans = ;
for(int i=;i<pos;i++) ans += dfs(pos - , i, ,);
return ans - pos + ;
} int main()
{
int t;
cin >> t;
memset(dp, -, sizeof(dp));
while(t--)
{
ll a, b;
scanf("%lld%lld", &a, &b);
ll ans = solve(b) - solve(a - );
printf("%lld\n", ans);
}
return ;
}
数位dp
E - Round Numbers
这个题目我第一感觉还比较简单。
题目大意:还是求在一个区间内满足条件的数
这个条件就是:这个数的二进制表示0比1的数多或者等于。
这个题目是二进制,那么我们就先把他转化成二进制,然后怎么写呢?
因为我们要求的是0比1 的数量多,既然有一个比较,那我就想到了上面的这个题目,它是要求左边的力矩等于右边的力矩,
这个也有一个等式或者不等式的关系,所以我们试着像上面那样处理,就是dp[i][j][k]表示第i位,出现0的个数,是不是满足条件
这个应该是状态唯一的吧,或者说是可以表示一类数。不管怎么样,先试试。
这个是可以的,但是当你敲代码的时候就会发现并不需要三维,我们只需要两维就可以了,
dp[i][j]表示第i位,满足条件的数,
敲完代码,过了样例wa了,搜了一下题解发现我忘记处理前导零了,这个肯定是要处理前导零的啊。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <algorithm>
#include <vector>
#include <string>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e5 + ;
const int first = ;
typedef long long ll;
ll dp[][];
int a[]; ll dfs(int pos,int num,bool limit,bool lead)
{
if (pos == -) return num >= first;
if (!lead&&!limit&&dp[pos][num] != -) return dp[pos][num];
int up = limit ? a[pos] : ;
ll ans = ;
for(int i=;i<=up;i++)
{
ans += dfs(pos - , lead&&(i==)?num:(i==?num+:num-), limit && (i == up),lead&&(i==));
}
if (!lead && !limit) dp[pos][num] = ans;
return ans;
} ll solve(ll x)
{
int pos = ;
while(x)
{
a[pos++] = x & ;
x >>= ;
}
return dfs(pos - , first, ,);
} int main()
{
int l, r;
memset(dp, -, sizeof(dp));
while(scanf("%d%d",&l,&r)!=EOF)
{
ll ans = solve(r)-solve(l-);
printf("%lld\n", ans);
}
return ;
}
数位dp
G - B-number
这个题目也很简单,题目大意 给你一个数,找到从1到这个数这个区间满足条件的数,这个条件就是可以被13整除,并且存在13这样的子串。
这个题目怎么写呢?我们的要求就是被13整除,所以需要这个数来表示这个,存在13的子串,所以要有一个来记录前缀,然后要判断是不是13
所以这就有三个数了,所以就可以设dp[i][j][k] 表示第i个数和为j,是不是满足有13的子串的要求。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <algorithm>
#include <vector>
#include <string>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e5 + ;
const int first = ;
typedef long long ll;
ll dp[][][];
int a[]; ll dfs(int pos, int pre, int sum, int flag, int limit) {
if (pos == -) return (flag==) && (sum == );
if (!limit && dp[pos][sum][flag] != -) return dp[pos][sum][flag];
int up = limit ? a[pos] : ;
ll ans = ;
for (int i = ; i <= up; i++) {
int f = ;
if (flag == ) f = flag;
else if (flag == && i == ) f = ;
else if (i == ) f = ;
ans += dfs(pos - , i, (sum * + i) % , f, limit && (i == up));
}
if (!limit) dp[pos][sum][flag] = ans;
return ans;
} ll solve(ll x) {
int pos = ;
while (x) {
a[pos++] = x % ;
x /= ;
}
return dfs(pos - , , , , );
} int main() {
int n;
memset(dp, -, sizeof(dp));
while (scanf("%d", &n) != EOF) {
ll ans = solve(n);
printf("%lld\n", ans);
}
return ;
}
数位dp
J - 吉哥系列故事――恨7不成妻
我开始以为这个题目特别简单,后来才发现自己在做梦。
这个题目我觉得还挺好,加深了我对于dp数组的理解,
之前我对于dp数组以为这个记录一类数,但是这个题目写完之后,我觉得这个数位dp的dp数组是记录一种状态,
这个状态往往和dfs里面的参数有关,也就是和题目本身有关,这个参数是来表示一类数的性质,这个性质就是题目的条件。
比如说这个题目,dp[i][j][k]这个 i 表示的就是第 i 位,前面的所有数字的和对7取模是 j ,到此为止它的数大小对7取模是k(把第 i 位当作个位来看)
然后dp本身就是表示的第i位以及之后 我们要求的cnt ,sum ,two
所以对于58_ 51_ 如果说以及枚举到了第三位 pos==3 的时候继续枚举5 然后枚举5后面的位数,因为limit==0 所以后面从0~9来枚举
这个时候 58 51 都是dp[3][6][2] 但是这个并不影响结果,因为这个时候我们是枚举58 51 之和的值,后面都是从0~9 而且51 58这两个数对于这个题目来说
其实是一样的状态就是,这个状态和题目要求的一一对应。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <algorithm>
#include <vector>
#include <string>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e5 + ;
const int first = ;
typedef long long ll;
const ll mod = 1e9 + ;
struct node
{
int cnt;
ll sum;
ll two;
node(int cnt=,ll sum=,ll two=):cnt(cnt),sum(sum),two(two){}
}dp[][][];
ll f[];
int a[]; node dfs(int pos, int sum, int num, bool limit) {
if (pos == -) return node(sum != && num != , , );
if (!limit&&dp[pos][sum][num].two != ) return dp[pos][sum][num];
int up = limit ? a[pos] : ;
node ans(,,);
for(int i=;i<=up;i++)
{
if (i == ) continue;
node ex = dfs(pos - , (sum * + i) % , (num + i) % , limit && (i == up));
ans.cnt += ex.cnt;
ans.cnt %= mod;
ans.sum = ans.sum + ((i * f[pos])%mod * ex.cnt)%mod + ex.sum;
ans.sum %= mod;
ans.two = ans.two + ((((i * f[pos]%mod) * (i*f[pos]%mod))%mod * ex.cnt%mod))%mod + * ((i*f[pos])%mod * ex.sum)%mod + ex.two;
ans.two %= mod;
}
if (!limit) dp[pos][sum][num] = ans;
return ans;
} ll solve(ll x) {
int pos = ;
while (x) {
a[pos++] = x % ;
x /= ;
}
ll ans = dfs(pos - , , , ).two;
ans %= mod;
return ans;
} int main() {
int t;
scanf("%d", &t);
f[] = ;
for (int i = ; i <= ; i++) f[i] = f[i - ] * ;
while (t--) {
ll l, r;
scanf("%lld%lld", &l, &r);
ll ans = (solve(r) - solve(l - ) + mod) % mod;
printf("%lld\n", ans);
}
return ;
}
数位dp
数位dp (2)的更多相关文章
- 【BZOJ1662】[Usaco2006 Nov]Round Numbers 圆环数 数位DP
[BZOJ1662][Usaco2006 Nov]Round Numbers 圆环数 Description 正如你所知,奶牛们没有手指以至于不能玩"石头剪刀布"来任意地决定例如谁 ...
- bzoj1026数位dp
基础的数位dp 但是ce了一发,(abs难道不是cmath里的吗?改成bits/stdc++.h就过了) #include <bits/stdc++.h> using namespace ...
- uva12063数位dp
辣鸡军训毁我青春!!! 因为在军训,导致很长时间都只能看书yy题目,而不能溜到机房鏼题 于是在猫大的帮助下我发现这道习题是数位dp 然后想起之前讲dp的时候一直在补作业所以没怎么写,然后就试了试 果然 ...
- HDU2089 不要62[数位DP]
不要62 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- 数位DP GYM 100827 E Hill Number
题目链接 题意:判断小于n的数字中,数位从高到低成上升再下降的趋势的数字的个数 分析:简单的数位DP,保存前一位的数字,注意临界点的处理,都是套路. #include <bits/stdc++. ...
- 数位dp总结
由简单到稍微难点. 从网上搜了10到数位dp的题目,有几道还是很难想到的,前几道基本都是模板题,供入门用. 点开即可看题解. hdu3555 Bomb hdu3652 B-number hdu2089 ...
- 数位DP入门
HDU 2089 不要62 DESC: 问l, r范围内的没有4和相邻62的数有多少个. #include <stdio.h> #include <string.h> #inc ...
- 数位DP之奥义
恩是的没错数位DP的奥义就是一个简练的dfs模板 int dfs(int position, int condition, bool boundary) { ) return (condition ? ...
- 浅谈数位DP
在了解数位dp之前,先来看一个问题: 例1.求a~b中不包含49的数的个数. 0 < a.b < 2*10^9 注意到n的数据范围非常大,暴力求解是不可能的,考虑dp,如果直接记录下数字, ...
- 数位DP
题意:(hdu 4734) 我们定义十进制数x的权值为f(x) = a(n)*2^(n-1)+a(n-1)*2(n-2)+...a(2)*2+a(1)*1,a(i)表示十进制数x中第i位的数字. 题目 ...
随机推荐
- 一个不错的spring 学习博客
http://www.iteye.com/blogs/subjects/spring-tittle-tattle
- [转] [知乎] 浅谈Roguelike
浅谈Roguelike 从柏林诠释说起 在2008年召开的国际Roguelike开发会议上,众多的Roguelike开发者与爱好者共同制定了<柏林诠释>,规定了Roguelike游戏需要具 ...
- Three.js实现3D地图实例分享
本文主要给大家介绍了关于利用Three.js开发实现3D地图的实践过程,文中通过示例代码介绍的非常详细,对大家学习或者使用three.js具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习 ...
- 用Python爬取大众点评数据,推荐火锅店里最受欢迎的食品
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:有趣的Python PS:如有需要Python学习资料的小伙伴可以加点 ...
- C# 基础知识系列- 11 委托和事件
0. 前言 事件和委托是C#中的高级特性,也是C#中很有意思的一部分.出现事件的地方,必然有委托出现:而委托则不一定会有事件出现.那为什么会出现这样的关系呢?这就需要从事件和委托的定义出发,了解其中的 ...
- stand up meeting 11/26/2015
part 组员 今日工作 工作耗时/h 明日计划 工作耗时/h UI 冯晓云 完成UI简易界面布局设计:在UI部分实现释义数据格式转换的实现和测试,使得其与外界接口均标准化为string,具体实现见 ...
- Anadi and Domino--codeforces div2
题目链接:https://codeforces.com/contest/1230/problem/C 题目大意:21枚多米诺牌,给你一个图,将多米诺牌放到图的边上,由同一个点发出的所有边,边上多米诺牌 ...
- 图2-4TCP状态转换图
这张图中描述了TCP中11个状态的转换. 光看这个图我一开始是蒙蔽的,也没有写服务器和客户端的操作流程.不过回头一想,是状态转换,也就是从一个状态到另外一个状态发生了什么,什么条件触发的.这样是不是好 ...
- JasperReports入门教程(一):快速入门
JasperReports入门教程(一):快速入门 背景 现在公司的项目需要实现一个可以配置的报表,以便快速的适应客户的需求变化.后来在网上查资料发现可以使用JasperReports + Jaspe ...
- tp5--路由的使用(初级)
在配置文件夹下的route.php文件配置路由: 控制器: 运行结果: