数位DP入门:(bzoj1833+3209)
//我是来看文章创建时间的= =
膜拜了一下蔡大神。。。。
人生第一道自己写的数位DP。。。好吧以前是看题解然后也不知道为什么就过了的>_< 虽然说现在还是只会裸题= =
数位DP介绍:
http://wenku.baidu.com/link?url=9OS5Ybpw5wx00ahrH8ED2oyIlR1uWwrxT8N4pEg27GgBt2T2hLe4sd_h1rmpY7P0HmeHIEDw9h6_K98dPhhjoMhD2TpKcS8w1X8cC_dkPp_
接下来是bzoj1833题目地址:
http://www.lydsy.com:808/JudgeOnline/problem.php?id=1833
题意挺明显。。
首先我萌可以用F[i,j,k]表示有i位数字且前导为k的数中总共含有多少个数字j(0<=j<=9)。。。
然后蒟蒻不想太麻烦(太弱)。。。干脆把1~9拆成9次一次一次来。。。。
因为题目要求的是[l,r],所以答案就是[0,r]-[0,l-1]......
假设当前求的是0~x的数中含有多少个数字num。。。
首先设x有w位数字,把x拆成w位(第一位为最低位)存在数组h里面,然后处理出x的后i位凑起来是什么数(也就是x的w个后缀)
用pre[i]表示10^(i-1)...10^i-1中含有数字num的个数(这个数对于1~9都是一样的)
那么假设处理到第i(i从最高位(w)开始枚举)位:
1、先考虑之后位上存在num的情况:
当前位取的数字小于h[i]的时候,有h[i]种情况(0~h[i]-1),此时之后的所有数都可以选(之后不管选什么数都不超过x),所以总个数+=h[i]*pre[i-1](当前位每一种情况都能给总个数贡献之后位中数字个数)
当前位取的数字就是h[i]的时候呢?那就华丽地无视掉啦(为什么?想一想。)(后面的位就等到后面再处理了。。)
2、考虑当前位为num的情况:
如果num=h[i],由于之前位上的数字都是上限了,之后的数不能超出x的范围(若之前位数有任意一个小于上限,那么之后的数可以随便选,则已被上面的步骤计算到),所以能贡献出(当前再后一个后缀的值+1)个答案。。。。(因为还有一种情况是后面的全选0)
num>h[i],那么不论之后怎么取,当前这一位都不会额外贡献任何个数。。。(因为想要合法,则前面一定有数小于那一位的上限,贡献在之前就记算了)
num<h[i],那么当取的数字为num的时候后面的数可以随便取,且每种情况都会额外贡献一个个数(也就是当前位上的这个),所以总个数+=10^(i-1)
当然以上是针对数码1~9的情况。。。。如果要求0的个数的话目测比较麻烦。。。当然可以在预处理的时候再开一维pre[i,j]表示i位数字前导为j的个数。。。。。
当然我萌发现,0出现的次数就是所有数字次数总和减去1~9的个数和= =
蒟蒻扯半天最终确定自己语死早了>_<。。。。
下面是更丑的代码TAT
var
pre,orz,h,sum:array[..]of int64;
ans,ans1:array[..]of int64;
i,j,k,n,m,mid:longint;
l,r,tot,tot1,l1,r1,x,w1,w2:int64;
procedure mahoshojo(x,num,w:int64);
var i:longint;anss:int64;
begin
anss:=;
for i:= to w do h[i]:=x div orz[i-] mod ;
for i:= to w do sum[i]:=x mod orz[i];
for i:=w downto do
begin
inc(anss,pre[i-]*h[i]);
if h[i]>num then inc(anss,orz[i-]);
if h[i]=num then inc(anss,sum[i-]+);
end;
ans[num]:=ans[num]+anss;
tot:=tot-anss;
end;
begin
pre[]:=;
orz[]:=;
for i:= to do orz[i]:=orz[i-]*;
for i:= to do pre[i]:=pre[i-]*+orz[i-];
readln(l,r);
dec(l);
tot:=;
if l> then
begin
l1:=l;
while l1> do begin inc(w1);l1:=l1 div end;
for i:= to w1- do inc(tot,(orz[i]-orz[i-])*i);
if w1> then inc(tot,w1*(l-orz[w1-]+)) else tot:=l+;
end
else
w1:=;
r1:=r;
while r1> do begin inc(w2);r1:=r1 div end;
tot1:=;
for i:= to w2- do inc(tot1,(orz[i]-orz[i-])*i);
if w2> then inc(tot1,w2*(r-orz[w2-]+)) else tot1:=r+;
// writeln(w2,':',tot1,' ',w1,':',tot);
for i:= to do
mahoshojo(l,i,w1);
for i:= to do ans[i]:=-ans[i];
ans[]:=tot;
// writeln(' ',tot);
tot:=tot1;
// writeln('!!!',tot1);
for i:= to do
mahoshojo(r,i,w2);
ans[]:=tot-ans[];
for i:= to do write(ans[i],' ');
writeln(ans[])
end.
话说记得类似的还有一道GDOI的题。。。。要求完全相反= =。。。给你1~某个数字中出现的各个数码的次数,要求判断是否存在这个数。。。
//当然强省数位DP都是T1某弱省就变成了T3(雾。。。或者是T4?。。那年5道题= =)了。。。。。
反正蒟蒻目测只会二分乱搞TAT.。。。。反正怎么玩都不会TLE2333
//四个月没碰键盘TAT。。。脑子还剩一点但是代码能力已经回档到两年前了>_<
//话说考前复习的时候来填坑显然花样作大死。。。YCL:哪有你这样的学生啊!。。。。。。。。
//作死成功。。。
接下来是bzoj3209题目地址:
http://www.lydsy.com:808/JudgeOnline/problem.php?id=3209
这种傻叉题只有我这种蒟蒻第一眼才没看出来= =
就是把1833的加改成了乘。。。。。
预处理出i位数中有j个1的情况总数(其实就是组合数= =组合数好久没打差点不会T_T)。。。。
然后就没什么可扯的了
var
c:array[..,..]of int64;
i,j,k:longint;
n,m,ans,bilibili,temp:int64;
num:array[..]of int64;
function qpow(a,b:int64):int64;
var date:int64;
begin
date:=;
while b> do
begin
if b and = then date:=date*a mod bilibili;
b:=b shr ;
if b> then a:=a*a mod bilibili
end;
exit(date)
end;
begin
bilibili:=;
readln(n);
m:=trunc(ln(n)/ln())+;
for i:= to m do c[i,]:=;
for j:= to m do
for i:= to m do
c[i,j]:=c[i-,j]+c[i-,j-];
i:=;
while n> do
begin
inc(i);
num[m-i+]:=n and ;
n:=n shr
end;
ans:=;
for i:= to m do
if num[i]= then
begin
for j:= to m-i do
ans:=(ans*qpow(temp+j,c[m-i,j]))mod bilibili;
ans:=ans*(temp+) mod bilibili;
inc(temp)
end;
writeln(ans)
end.
II
数位DP入门:(bzoj1833+3209)的更多相关文章
- xbz分组题B 吉利数字 数位dp入门
B吉利数字时限:1s [题目描述]算卦大湿biboyouyun最近得出一个神奇的结论,如果一个数字,它的各个数位相加能够被10整除,则称它为吉利数.现在叫你计算某个区间内有多少个吉利数字. [输入]第 ...
- 数位dp入门 hdu2089 不要62
数位dp入门 hdu2089 不要62 题意: 给定一个区间[n,m] (0< n ≤ m<1000000),找出不含4和'62'的数的个数 (ps:开始以为直接暴力可以..貌似可以,但是 ...
- hdu3555 Bomb 数位DP入门
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555 简单的数位DP入门题目 思路和hdu2089基本一样 直接贴代码了,代码里有详细的注释 代码: ...
- HDU 2089 不要62【数位DP入门题】
不要62 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submis ...
- HDU 2089 不要62(数位dp入门)
题意:统计区间 [a,b] 中不含 4 和 62 的数字有多少个. 题解:这是数位DP的入门题了,首先要理解数DP的原理,DP[i][j]:代表第i位的第j值,举个栗子:如4715 数位数是从右向 ...
- HDU 2089 - 不要62 - [数位DP][入门题]
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2089 Time Limit: 1000/1000 MS (Java/Others) Memory Li ...
- LightOJ 1140 计数/数位DP 入门
题意: 给出a,b求区间a,b内写下过多少个零 题解:计数问题一般都会牵扯到数位DP,DP我写的少,这道当作入门了,DFS写法有固定的模板可套用 dp[p][count] 代表在p位 且前面出现过co ...
- 【数位dp】bzoj1833: [ZJOI2010]count 数字计数
数位dp姿势一直很差啊:顺便庆祝一下1A Description 给定两个正整数a和b,求在[a,b]中的所有整数中,每个数码(digit)各出现了多少次. Input 输入文件中仅包含一行两个整数a ...
- HDU-2089不要62-暴力或数位DP入门
不要62 题意:给定区间,求在这个区间中有多少个数字,不包含4且不包含62: 这道题作为数位DP的入门题: 暴力也是可以过 #include<cstdio> #include <io ...
随机推荐
- Lvs+keepAlived实现负载均衡高可用集群(DR实现)
第1章 LVS 简介 1.1 LVS介绍 LVS是Linux Virtual Server的简写,意为Linux虚拟服务器,是虚拟的服务器集群系统,可在UNIX/LINUX平台下实现负载均衡集群功能. ...
- (转)为Xcode添加删除行、复制行快捷键
转摘链接:http://www.jianshu.com/p/cc6e13365b7e 在使用eclipse过程中,特喜欢删除一行和复制一行的的快捷键.而恰巧Xcode不支持这两个快捷键,再一次的恰巧让 ...
- iOS 蓝牙开发资料记录
一.蓝牙基础认识: 1.iOS蓝牙开发: iOS蓝牙开发:蓝牙连接和数据读写 iOS蓝牙后台运行 iOS关于app连接已配对设备的问题(ancs协议的锅) iOS蓝牙空中 ...
- APP闪退问题
1.iOS-中app启动闪退的原因 2.iOS开发-闪退问题-解决之前上架的 App 在 iOS 9 会闪退问题 3.iOS-应用闪退总结 4.iOS开发-捕获程序崩溃日志 5.iOS开发-应用崩溃日 ...
- iOS开发富文本制作 图片和文字/NSMutableParagraphStyle/NSMutableAttributedString
/NSMutableParagraphStyle/NSMutableAttributedString 组合使 NSString * titlestr=@"日产GT-R"; NSMu ...
- [置顶]
xamarin Tablayout+Viewpager+Fragment顶部导航栏
最近几天不忙,所以把项目中的顶部导航栏的实现归集一下.android中使用TabLayout+ViewPager+Fragment制作顶部导航非常常见,代码实现也比较简单.当然我这个导航栏是基于xam ...
- lodash源码分析之Hash缓存
在那小小的梦的暖阁,我为你收藏起整个季节的烟雨. --洛夫<灵河> 本文为读 lodash 源码的第四篇,后续文章会更新到这个仓库中,欢迎 star:pocket-lodash gitbo ...
- Mysql数据库重要知识点(知了堂学习心得)
Mysql数据库知识点 1.管理数据库语句: 使用数据库: use test; 添加数据库: create database 数据库名; create database test; 修改数据库: al ...
- win10下部署.Net Web项目到IIS10
本问主要介绍如何将.Net Web项目部署到IIS10下面. 1.确保iis功能已开启 开启步骤如下:控制面板->程序 点击确定,ok,iis功能已开启. 2.打开iis,绑定站点到iis下面 ...
- 如何配置FTP服务器,方便操作服务器文件
1 进入"控制面板"->"程序"->"打开或关闭Windows功能",找到"Internet信息服务"选项 ...