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

給定 

1405402477702.png

輸入

輸入數據僅一行包含三個整數,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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章