hihoCoder1033 交错和 数位DP
题目:交错和
链接:http://hihocoder.com/problemset/problem/1033#
题意:对于一个十进制整数x,令a0、a1、a2、...、an是x从高位到低位的数位,定义f(x)=a0-a1+a2-a3+...an,给出L、R、K,x在L到R之间,求所有满足:f(x)=k的x的和。(0 ≤ l ≤ r ≤ 10^18, |k| ≤ 100)
思路:
L与R太大,连预处理的可能性都没有,很明显的数位DP。
令dp[i][j]为精确的(有前导0)i 位,f(x)值为j 的x的和
令dd[i][j]为精确的i 位,f(x)值为j 的x的个数。
dp[1][i] = i (i从0-9)
dd[1][i] = 1(i从0-9)
当i为奇数时,最后一位前的符号位+,所以dp[i][j] = dp[i][j] + dp[i-1][j-u]*10 + u*dd[i-1][j-u] (u从0-9)
dd[i][j]=dd[i][j] + dd[i-1][j-u] (u从0-9)
当i为偶数时,将j-u改成j+u即可
注意这里的dp求的和是有前导0的,比如3位数里098的f值为0-9+8也就是-1,所以dp[3][k]并不是0到1000里f值为k的数的和,因此我们要重新计算一个不含前导0的。
令op[i][j]为i 位,f(x)值为j 的x的和
令pp[i][j]为i 位,f(x)值为j 的x的个数。
递推方法与dp一样,不同的是初始化,特别的令pp[1][0]=0,这样,等会递推出来的就是不包含前导0的,之后,为了方便,我们可以重新定义op[i][j]为前i 位,f(x)值为j 的x的和,pp也一样,进行下前缀和计算就可以了。
解决完以上两步,这个问题便简单很多了,l到r,我们可以先算出0-r的,再减去0-l的,因此问题就转化成x属于0-l,f(x)值为k的x的和了,比如说3256,那么我们可以先算1000里有多少,1000-2000有多少,2000-3000有多少,再算3000-3100里有多少,3100-3200里有多少......1000里的直接就是op[3][k],1000到2000的,我们可以遍历u从0-9,现在就是1-u+?-?=k有多少了,那么?-?的值应该是k-1+u,也就是op[2][k-1+u],同时注意下细节就可以了。具体看代码。
注:值得注意的是dd[0][0]=1,pp[0][0]=1
#include<stdio.h>
#include<iostream>
using namespace std;
#define Mod 1000000007
typedef long long LL;
LL dp[][]={};
LL dd[][]={};
LL op[][]={};
LL pp[][]={};
int getPos(int val)
{
return val+;
}
void Init()
{
dd[][]=;
for(int i=;i<=;i++) dd[][getPos(i)]=,dp[][getPos(i)]=i;
for(int i=;i<=;i++)
{
if(i&)
{
for(int j=;j<;j++)
{
for(int k=j;k<=;k++)
{
dp[i][k]=(dp[i][k]+dp[i-][k-j]*%Mod+j*dd[i-][k-j]%Mod)%Mod;
dd[i][k]=(dd[i][k]+dd[i-][k-j])%Mod;
}
}
}
else
{
for(int j=;j<;j++)
{
for(int k=;k<=-j;k++)
{
dp[i][k]=(dp[i][k]+dp[i-][k+j]*%Mod+j*dd[i-][k+j]%Mod)%Mod;
dd[i][k]=(dd[i][k]+dd[i-][k+j])%Mod;
}
}
}
} for(int i=;i<=;i++) pp[][getPos(i)]=,op[][getPos(i)]=i;
pp[][getPos()]=;
for(int i=;i<=;i++)
{
if(i&)
{
for(int j=;j<;j++)
{
for(int k=j;k<=;k++)
{
op[i][k]=(op[i][k]+op[i-][k-j]*%Mod+j*pp[i-][k-j]%Mod)%Mod;
pp[i][k]=(pp[i][k]+pp[i-][k-j])%Mod;
}
}
}
else
{
for(int j=;j<;j++)
{
for(int k=;k<=-j;k++)
{
op[i][k]=(op[i][k]+op[i-][k+j]*%Mod+j*pp[i-][k+j]%Mod)%Mod;
pp[i][k]=(pp[i][k]+pp[i-][k+j])%Mod;
}
}
}
}
pp[][getPos()]=;
for(int i=;i<=;i++)
{
for(int j=;j<=;j++)
{
op[i][j]=(op[i][j]+op[i-][j])%Mod;
pp[i][j]=(pp[i][j]+pp[i-][j])%Mod;
}
}
} LL solve(LL x,LL p)
{
if(x<) return ;
LL tmp=x;
int bt[],bo=;
while(x)
{
bt[bo++]=x%;
x/=;
}
LL io=;
for(int i=;i<bo;i++)
io=io*;
LL sum=,k=,kk=;
for(int i=bo-;i>;i--)
{
if((bo-i)&)
{
for(int j=;j<bt[i];j++)
{
if(i==bo-&&j==)
{
sum=(sum+op[i][getPos(p)])%Mod;
}
else
{
for(int u=;u<=;u++)
{
sum=(sum+(kk*%Mod+j*+u)%Mod*io/%Mod*dd[i-][getPos(p+u-j-k)]%Mod+dp[i-][getPos(p+u-j-k)])%Mod;
}
}
}
k+=bt[i];
kk=(kk*%Mod+bt[i])%Mod;
}
else
{
for(int j=;j<bt[i];j++)
{
sum=(sum+(kk*%Mod+j)%Mod*io%Mod*dd[i][getPos(p+j-k)]%Mod+dp[i][getPos(p+j-k)])%Mod;
}
k-=bt[i];
kk=(kk*%Mod+bt[i])%Mod;
}
io/=;
}
if(bo&)
{
for(int i=;i<=bt[];i++)
if(p-k==i)
{
sum=(sum+kk*%Mod+i)%Mod;
}
}
else
{
for(int i=;i<=bt[];i++)
if(k-p==i) sum=(sum+kk*%Mod+i)%Mod;
}
return sum;
}
int main()
{
Init();
LL l,r,k;
cin>>l>>r>>k;
cout<<(solve(r,k)-solve(l-,k)+Mod)%Mod<<endl;
return ;
}
AC代码
hihoCoder1033 交错和 数位DP的更多相关文章
- [hihocoder 1033]交错和 数位dp/记忆化搜索
#1033 : 交错和 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描写叙述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1 ...
- hihoCoder 1033 : 交错和 数位dp
思路:数位dp,dp(i, j, k)表示考虑i位数,每位数可以任意取[0~9],并且这i位数的交错和为j,k=1表示前缀全是0(如000456),k=0表示前缀不为0.注意,前缀是否为0是这道题的一 ...
- HihoCoder 1033交错和(数位DP第三题)
(写挂了,有空再补) 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1,定义 ...
- 数位dp/记忆化搜索
一.引例 #1033 : 交错和 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an ...
- 【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++. ...
随机推荐
- (转)Spring Boot(八):RabbitMQ 详解
http://www.ityouknow.com/springboot/2016/11/30/spring-boot-rabbitMQ.html RabbitMQ 即一个消息队列,主要是用来实现应用程 ...
- @RequestParam 和@RequestBody 的区别?
@RequestParam用来接收: 1 用来处理简单的参数绑定 2 用来接收 Content-Type 是 application/x-www-form-urlencoded (这种格 式的数据 ...
- executequery要求已打开且可用的connection,连接的当前状态为已关闭
问题: executequery要求已打开且可用的connection,连接的当前状态为已关闭 错误原因: 连接的当前状态为已关闭.或者只创建了Connection对象,没有调用Connection. ...
- Jmeter-csv文件参数化
本文以登录的用户名和密码为例 1 创建csv文件 创建.csv文件,用户名和密码中间以逗号隔开 图 1 创建csv文件 2 在线程组中添加并配置CSV Data Set Config 添加 ...
- UVA11584-Partitioning by Palindromes(动态规划基础)
Problem UVA11584-Partitioning by Palindromes Accept: 1326 Submit: 7151Time Limit: 3000 mSec Problem ...
- Request Body可以反复读取的方法
org.springframework.web.filter.HiddenHttpMethodFilter:过滤器已经读取流了,因此想频繁读取流的话,自定义Filter必须在org.springfra ...
- JDK动态代理(1)-----------new 对象的方式
//case 1: 直接newHelloWorldImpl helloWorldImpl = new HelloWorldImpl(); //case 2: 反射拿到类之后,通过newInstance ...
- Apollo内核版本安装
参考:https://github.com/ApolloAuto/apollo/blob/master/docs/quickstart/apollo_software_installation_gui ...
- Flink知识点
1. Flink.Storm.Sparkstreaming对比 Storm只支持流处理任务,数据是一条一条的源源不断地处理,而MapReduce.spark只支持批处理任务,spark-streami ...
- Vue2.x源码学习笔记-Vue实例的属性和方法整理
还是先从浏览器直观的感受下实例属性和方法. 实例属性: 对应解释如下: vm._uid // 自增的id vm._isVue // 标示是vue对象,避免被observe vm._renderProx ...