hihocoder1033(数位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,dp[pos][aim][len%2],记录的是,长度为len,从pos以下位置,在没有任何约束的情况下,结果为aim的交错和。增加一维[len%2]是因为len的奇偶性会影响pos后每位的正负性。dp中,sum为所有结果为aim的数的交错和,n为所有结果为aim的数的个数。

代码:

/******************************************************
* @author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;

#define eps 1e-8
#define zero(_) (abs(_)<=eps)
const double pi=acos(-1.0);
typedef long long LL;
const int Max=22;
const LL INF=1e9+7;
int bit[Max];
int len;
int p=0;
struct node
{
    LL sum;
    LL n;
};
node dp[22][400][2];
LL help[22];
node dfs(int pos,int aim,bool limit,bool stt)
{
    node re;
    re.n=0;
    re.sum=0;
    if(pos==0)
    {
        if(aim==100)
            re.n=1;
        return re;
    }
    if(!limit&&!stt&&dp[pos][aim][len%2].n!=-1)
    {
        return dp[pos][aim][len%2];
    }
    int end=limit?bit[pos]:9;
    int st= stt?1:0;
    for(int i=st; i<=end; i++)
    {
        int add=((len-pos)%2==0?-1:+1);
        node next=dfs(pos-1,aim+add*i,limit&&i==end,0);
        re.sum=(re.sum+next.sum+next.n*help[pos]*i%INF)%INF;
        re.n=(re.n+next.n)%INF;
    }
    if(!limit&&!stt)
        return dp[pos][aim][len%2]=re;
    return re;
}
LL getans(LL n,int aim)
{
    if(n<=0)
        return 0;
    p=0;
    while(n)
    {
        bit[++p]=n%10;
        n/=10;
    }
    LL ans=0;
    for(len=1; len<=p; len++)
    {
        ans=(ans+dfs(len,aim+100,len==p,1).sum)%INF;
    }
    return ans;
}
int main()
{
    LL l,r;
    int aim;
    memset(dp,-1,sizeof dp);
    help[1]=1;
    for(int i=2;i<22;i++)
    help[i]=(help[i-1]*10)%INF;
    while(cin>>l>>r>>aim)
    {
        cout<<(getans(r,aim)-getans(l-1,aim)+INF)%INF<<endl;
    }
    return 0;
}
时间: 2024-10-08 20:49:47

hihocoder1033(数位dp)的相关文章

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

51Nod 1009 数字1的个数 | 数位DP

题意: 小于等于n的所有数中1的出现次数 分析: 数位DP 预处理dp[i][j]存 从1~以j开头的i位数中有几个1,那么转移方程为: if(j == 1) dp[i][j] = dp[i-1][9]*2+pow(10,i-1);else dp[i][j] = dp[i-1][9]+dp[i][j-1]; 然后注意下对于每个询问统计的时候如果当前位为1需要额外加上他后面所有位数的个数,就是n%pow(10,i-1); 这样总复杂度log(n)*10 #include <bits/stdc++.

HDU 3555 Bomb (数位DP)

数位dp,主要用来解决统计满足某类特殊关系或有某些特点的区间内的数的个数,它是按位来进行计数统计的,可以保存子状态,速度较快.数位dp做多了后,套路基本上都差不多,关键把要保存的状态给抽象出来,保存下来. 简介: 顾名思义,所谓的数位DP就是按照数字的个,十,百,千--位数进行的DP.数位DP的题目有着非常明显的性质: 询问[l,r]的区间内,有多少的数字满足某个性质 做法根据前缀和的思想,求出[0,l-1]和[0,r]中满足性质的数的个数,然后相减即可. 算法核心: 关于数位DP,貌似写法还是

51nod1043(数位dp)

题目链接:https://www.51nod.com/onlineJudge/questionCode.html#!problemId=1043 题意:中文题诶- 思路:数位dp 我们用dp[i][j]来存储长度为2*i且一半和为j的所有情况(包括前导0的情况),为了方便我们现在只讨论其一半的和的情况,因为如果包括前导0的话其两边的情况是一样的: 我们假设再长度为i-1的数字最前面加1位数字k,0<=k<=9(这位数字加在哪里并不影响答案,因为我们在计算i-1长度的时候已经计算了所有组合情况,

数位dp

1.[hdu3709]Balanced Number 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<string> 5 #include<cstdlib> 6 #include<algorithm> 7 #include<ctime> 8 #include<cmath> 9 #include<queue>

【HDU 3652】 B-number (数位DP)

B-number Problem Description A wqb-number, or B-number for short, is a non-negative integer whose decimal form contains the sub- string "13" and can be divided by 13. For example, 130 and 2613 are wqb-numbers, but 143 and 2639 are not. Your task

hdu 5898 odd-even number 数位DP

odd-even number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 716    Accepted Submission(s): 385 Problem Description For a number,if the length of continuous odd digits is even and the length

LightOJ1068 Investigation(数位DP)

这题要求区间有多少个模K且各位数之和模K都等于0的数字. 注意到[1,231]这些数最大的各位数之和不会超过90左右,而如果K大于90那么模K的结果肯定不是0,因此K大于90就没有解. 考虑到数据规模,数据组数,这题状态这么表示: dp[i][j][k]:位数为i模K结果为j且各位数之和模K结果为k的数字个数 然后就是转移方程,最后就是统计.. 统计部分好棘手...半乱搞下AC的..还是对数位DP的这一部分太不熟悉了. 1 #include<cstdio> 2 #include<cstr

HDU 4734 F(x)(数位DP)

Description For a decimal number x with n digits (A nA n-1A n-2 ... A 2A 1), we define its weight as F(x) = A n * 2 n-1 + A n-1 * 2 n-2 + ... + A 2 * 2 + A1 * 1. Now you are given two numbers A and B, please calculate how many numbers are there betwe