数位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位的数字. 题目 ...
随机推荐
- 通过STC15F2K60S2控制SIM900A发中英文短信,打电话
本文通过串口通信,使用STC15系列单片机实现发短信打电话功能. 一. 注意事项 1. 首先要确定手机卡已经注册到网络,具备打电话发短信功能 2. 正确的硬件连接: P3.0-----STXD或者5V ...
- Linux远程登陆
Linux 远程登录 Linux一般作为服务器使用,而服务器一般放在机房,你不可能在机房操作你的Linux服务器. 这时我们就需要远程登录到Linux服务器来管理维护系统. Linux系统中是通过ss ...
- alg-最长公共子序列
class Solution { public: std::string LongestCommonSubsequence(const std::string& s1, const std:: ...
- 事务的传播属性及隔离级别 Spring
事务的传播属性(Propagation) REQUIRED ,这个是默认的属性 Support a current transaction, create a new one if none exis ...
- 获取SVG中g标签的宽度高度及位置坐标
1. 问题的出现 对于普通的HTML元素,有很多获得其宽度width.高度height.距左left.距顶top等属性的方法: 类似offsetWidth,clientWidth,width之类的,通 ...
- Extended Traffic LightOJ - 1074 (经典SPFA问题)
题目大意:每一个城市都有一定的繁荣度,然后给出m条有向边i->j,定义这条边的权值为pow(arr[j]-arr[i],3),然后给你q个询问,每个询问输入一个x. 然后问你点1到x的距离,如果 ...
- 深度学习之文本分类模型-前馈神经网络(Feed-Forward Neural Networks)
目录 DAN(Deep Average Network) Fasttext fasttext文本分类 fasttext的n-gram模型 Doc2vec DAN(Deep Average Networ ...
- react-devtools安装调试
初学react,Chrome F12调试,需要一款插件react-devtools. 网上大多对于翻墙不利索的同学大多才用了git源码.npm本地手动打包Chrome拓展程序.如:https://ww ...
- 浅析 CSS 中的边距重叠
浅析 CSS 中的边距重叠 边距重叠是什么 在说边距重叠之前,先以正常的思维来考虑如果你现在是浏览器引擎遇到这种情况应该怎么办? 现在有两个元素 div1 和 div2 紧挨着,中间没有它元素,它们的 ...
- C# WCF之用接口创建服务契约、部署及客户端连接
服务契约描述了暴露给外部的类型(接口或类).服务所支持的操作.使用的消息交换模式和消息的格式.每个WCF服务必须实现至少一个服务契约.使用服务契约必须要引用命名空间System.ServiceMode ...