hihoCoder #1033 : 交错和 (数位Dp)

题目大意:

给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1,定义交错和函数:

f(x) = a0 - a1 + a2 - ... + ( - 1)n - 1an - 1

例如:

f(3214567) = 3 - 2 + 1 - 4 + 5 - 6 + 7 = 4

给定

输入

输入数据仅一行包含三个整数,l, r, k(0 ≤ l ≤ r ≤ 1018, |k| ≤ 100)。

输出

输出一行一个整数表示结果,考虑到答案可能很大,输出结果模 109 + 7。

提示

对于样例 ,满足条件的数有 110 和 121,所以结果是 231 = 110 + 121。

更多样例:

Input
4344 3214567 3
Output
611668829
Input
404491953 1587197241 1
Output
323937411
Input
60296763086567224 193422344885593844 10
Output
608746132
Input
100 121 -1
Output
120

样例输入

100 121 0

样例输出

231

题目分析:定义状态dp(len,x,k)表示长度为len,开头数字为x,交错和为k的所有数之和,num(len,x,k)为上述状态的数的个数。则通过递推即可得到这两个状态组,然后构造答案即可。

ps:这道题贼恶心。。。每一步加或乘运算后必须取余,否则结果一定错误。

代码如下:
# include<iostream>
# include<cstdio>
# include<map>
# include<set>
# include<queue>
# include<vector>
# include<list>
# include<cstring>
# include<algorithm>
using namespace std;
# define LL long long

const int N=1000000000;
const int mod=1000000007;

int bit[20];
LL num[25][10][205];
LL dp[25][10][205];
LL base[20];

bool ok(int x)
{
	return x>=-100&&x<=100;
}

void init()
{
	base[0]=base[1]=1;
	for(int i=2;i<=20;++i)
		base[i]=(base[i-1]*10)%mod;
	memset(num,0,sizeof(num));
	memset(dp,0,sizeof(dp));
	for(int i=0;i<10;++i){
		num[1][i][i+100]=1;
		dp[1][i][i+100]=i;
	}
	int flag=1;
	for(int i=1;i<20;++i){
		flag*=-1;
		for(int j=0;j<10;++j){
			for(int k=-100;k<=100;++k){
				for(int l=0;l<10;++l) if(ok(k+flag*l)){
					num[i+1][j][k+flag*l+100]+=num[i][j][k+100];
					num[i+1][j][k+flag*l+100]%=mod;
					dp[i+1][j][k+flag*l+100]+=((dp[i][j][k+100]*10)%mod+(num[i][j][k+100]*l)%mod)%mod;
					dp[i+1][j][k+flag*l+100]%=mod;
				}
			}
		}
	}
}

LL solve(LL x,int k)
{
	if(x<0) return 0ll;
	LL temp=x;
	bit[0]=0;
	while(x>0){
		bit[++bit[0]]=x%10;
		x/=10;
	}
	LL res=0;
	for(int i=1;i<bit[0];++i)
		for(int j=1;j<10;++j){
			res+=dp[i][j][k+100];
			res%=mod;
		}
	int t=0;
	int flag=1;
	LL tt=0ll;
	for(int i=bit[0];i>=1;--i){
		int low=(i==bit[0])?1:0;
		for(int j=low;j<bit[i];++j){
			LL tres=((tt*num[i][j][(k-t)/flag+100])%mod+dp[i][j][(k-t)/flag+100])%mod;
			res=(res+tres)%mod;
		}
		t+=flag*bit[i];
		tt=(tt+(bit[i]*base[i])%mod)%mod;
		flag*=-1;
	}
	if(t==k)
		res=(res+temp)%mod;
	return res;
}

int main()
{
	init();
	LL k,l,r;
	//freopen("in.txt","r",stdin);
	while(~scanf("%lld%lld%d",&l,&r,&k))
	{
		LL a=solve(r,k);
		LL b=solve(l-1,k);
		if(a<b) a+=mod;
		printf("%lld\n",a-b);
	}
	return 0;
}

  

时间: 2024-08-27 11:25:38

hihoCoder #1033 : 交错和 (数位Dp)的相关文章

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

#1033 : 交错和 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0,?a1,?...,?an?-?1,定义交错和函数: f(x)?=?a0?-?a1?+?a2?-?...?+?(?-?1)n?-?1an?-?1 例如: f(3214567)?=?3?-?2?+?1?-?4?+?5?-?6?+?7?=?4 给定 输入 输入数据仅一行包含三个整数,l,?r,?k(0?≤?l?≤?r?≤?1018,?|k|

hihoCoder #1033 : 交错和 [ 数位dp ]

传送门 #1033 : 交错和 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1,定义交错和函数: f(x) = a0 - a1 + a2 - ... + ( - 1)n - 1an - 1 例如: f(3214567) = 3 - 2 + 1 - 4 + 5 - 6 + 7 = 4 给定 l, r, k,求在 [l, r] 区间中,所有 f(x) = k 的 x 的和,即

[数位dp] hihoCoder 1033 交错和

题意: 问你[l,r]区间内的所有满足各个位一加一减最后和是k的全有数的和. 思路: 数位dp dp[site][sum][p][k] 代表site位,和是sum,当前是加还是减,最后和是k的数的和以及个数 也就是存成结构体. 然后求的时候 ans.cnt=(ans.cnt+cur.cnt)%mod; ans.sum=(ans.sum+cur.sum+cur.cnt*tep)%mod; tep为i*当前位的位权. 代码: #include"cstdlib" #include"

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

hihoCoder 1033: 交错和

(1)题目描述: 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1,定义交错和函数: f(x) = a0 - a1 + a2 - ... + ( - 1)n - 1an - 1 例如: f(3214567) = 3 - 2 + 1 - 4 + 5 - 6 + 7 = 4 给定 输入 输入数据仅一行包含三个整数,l, r, k(0 ≤ l ≤ r ≤ 1018, |k| ≤ 

hiho 1033 —— 交错和 【数位DP】

1033 : 交错和 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 x,设它十进制展从高位到低位上的数位依次是 a0, a1, ..., an - 1,定义交错和函数: f(x) = a0 - a1 + a2 - ... + ( - 1)n - 1an - 1 例如: f(3214567) = 3 - 2 + 1 - 4 + 5 - 6 + 7 = 4 给定 l, r, k,求在 [l, r] 区间中,所有 f(x) = k 的 x 的和,即: 输入

【hihoCoder】1033: 交错和

初探数位dp 介绍了数位类统计的基础知识.以下列出其中的基础点: 基本问题 统计在区间[l, r]中满足条件的数的个数 思路 1. [l, r] 将问题转换为 在[0, r]中满足条件的个数 - 在[0, l)满足条件的个数 2. 求解 区间[0, n]满足条件的个数 性质:一个小于n的数m,一定是从高位到低位在某一位小于n的对应位的一个数   数值 百位 十位 个位   n 358 3 5 8   m 350 3 5 0 0<8 m 349 3 4 9 4<5 遍历所有小于n的数:从高位到低

hihocoder #1301 : 筑地市场 数位dp+二分

题目链接: http://hihocoder.com/problemset/problem/1301?sid=804672 题解: 二分答案,每次判断用数位dp做. #include<iostream> #include<cstring> #include<cstdio> using namespace std; typedef long long LL; const LL INFLL = 0x3f3f3f3f3f3f3f3fLL; //dp[x][0]表示高位还没有出

[hdu 4933]Miaomiao&#39;s Function 数位DP+大数

Miaomiao's Function Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 79    Accepted Submission(s): 18 Problem Description Firstly , Miaomiao define two functions f(x) , g(x): (K is the smallest