题目:交错和

链接: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的更多相关文章

  1. [hihocoder 1033]交错和 数位dp/记忆化搜索

    #1033 : 交错和 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描写叙述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1 ...

  2. hihoCoder 1033 : 交错和 数位dp

    思路:数位dp,dp(i, j, k)表示考虑i位数,每位数可以任意取[0~9],并且这i位数的交错和为j,k=1表示前缀全是0(如000456),k=0表示前缀不为0.注意,前缀是否为0是这道题的一 ...

  3. HihoCoder 1033交错和(数位DP第三题)

    (写挂了,有空再补) 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1,定义 ...

  4. 数位dp/记忆化搜索

    一.引例 #1033 : 交错和 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an  ...

  5. 【BZOJ1662】[Usaco2006 Nov]Round Numbers 圆环数 数位DP

    [BZOJ1662][Usaco2006 Nov]Round Numbers 圆环数 Description 正如你所知,奶牛们没有手指以至于不能玩"石头剪刀布"来任意地决定例如谁 ...

  6. bzoj1026数位dp

    基础的数位dp 但是ce了一发,(abs难道不是cmath里的吗?改成bits/stdc++.h就过了) #include <bits/stdc++.h> using namespace ...

  7. uva12063数位dp

    辣鸡军训毁我青春!!! 因为在军训,导致很长时间都只能看书yy题目,而不能溜到机房鏼题 于是在猫大的帮助下我发现这道习题是数位dp 然后想起之前讲dp的时候一直在补作业所以没怎么写,然后就试了试 果然 ...

  8. HDU2089 不要62[数位DP]

    不要62 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submis ...

  9. 数位DP GYM 100827 E Hill Number

    题目链接 题意:判断小于n的数字中,数位从高到低成上升再下降的趋势的数字的个数 分析:简单的数位DP,保存前一位的数字,注意临界点的处理,都是套路. #include <bits/stdc++. ...

随机推荐

  1. 【Linux基础】awk命令

    1.awk命令说明 (1)awk是行处理器: 相比较屏幕处理的优点,在处理庞大文件时不会出现内存溢出或是处理缓慢的问题,通常用来格式化文本信息 (2)awk处理过程:  依次对每一行进行处理,然后输出 ...

  2. ES5-ES6-ES7_Promise对象详解

    Promise对象概述(什么是Promise) Promise 是异步编程的一种解决方案,比传统的异步解决方案——回调函数和事件——更合理和更强大 所谓Promise,简单说就是一个容器,里面保存着某 ...

  3. 利用nginx搭建小型的文件服务器

    PS内的文件如果需要共享给其他计算机下载,可以选择ftp的方式,优点是操作性很高,修改删除下载等等都可以,但是速度略慢. 如果仅仅是将VPS作为文件中转站,可以尝试用Nginx架设一个简单的文件服务器 ...

  4. centos7下kubernetes(3。部署kubernetes)

    环境:三个centos7 K8s2是Master;K8s1是node1:K8s3是node2 官方文档:https://kubernetes.io/docs/setup/independent/ins ...

  5. xss攻击(跨站脚本)

    原理跨站脚本(Cross site script,简称xss)是一种“HTML注入”,由于攻击的脚本多数时候是跨域的,所以称之为“跨域脚本”. 我们常常听到“注入”(Injection),如SQL注入 ...

  6. python笔记31-使用ddt报告出现dict() -> new empty dictionary dict(mapping) 问题解决

    使用ddt框架生成html报告的时候,出现:dict() -> new empty dictionary dict(mapping) -> new dictionary initializ ...

  7. [matlab] 22.matlab图论实例 最短路问题与最小生成树 (转载)

    最短路问题之 Floyd 某公司在六个城市 c1c1,c2c2,….,c6c6 中有分公司,从 cici 到 cjcj 的直接航程票价记在下述矩阵的 (ii,jj) 位置上. (∞∞表示无直接航路), ...

  8. Nginx入门讲解——初步认识了解nginx.conf配置文件以及配置多个虚拟主机

    本文引自网络进攻学习之用https://blog.csdn.net/weixin_38111957/article/details/81080539 一. 引言上节文章讲述了如何用信号控制Nginx服 ...

  9. tomcat 安装配置部署到nginx+tomcat+https

    目录 1 Tomcat简介 2.下载并安装Tomcat服务 2.2 部署java环境 2.3 安装Tomcat 2.4 Tomcat目录介绍 (关注点 bin conf logs webapps) 2 ...

  10. Windows系统中内存泄露与检测工具及方法

    1.检测需要使用的工具:windbg工具.检测前,需要先安装windbg工具.安装了该工具后,会在安装目录下有一个umdh工具.假设windbg安装在以下目录下:D:\Program Files\De ...