hihocoder#1033 : 交错和(数位DP)

版权声明:http://blog.csdn.net/Mitsuha_。 https://blog.csdn.net/Mitsuha_/article/details/82152976

时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
给定一个数 x ,设它十进制展从高位到低位上的数位依次是 a 0 , a 1 , . . . , a n 1 ,定义交错和函数:

f ( x ) = a 0 a 1 + a 2 . . . + ( 1 ) n 1 a n 1

例如:

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

给定 l , r , k ,求在 [ l , r ] 区间中,所有 f ( x ) = k x 的和,即:

x = l r [ f ( x ) = k ] x

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

输出
输出一行一个整数表示结果,考虑到答案可能很大,输出结果模 10 9 + 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,用结构体 d [ i ] [ s u m ] [ 0 / 1 ] 存储前 i 位的交错和为 s u m 0 / 1 表示在第 i 位是 + a i / a i 的数的和以及这些数的个数。

交错和可能为负,所以假定 s u m = 200 的时候和为0。

#include<bits/stdc++.h>
using namespace std;
const int MAX=1e6+10;
const int MOD=1e9+7;
const double PI=acos(-1.0);
typedef long long ll;
struct lenka
{
    ll sum,cnt;
}d[20][10][400][2];
int p[20];
ll f[20];
ll cal(ll x,ll num)
{
    if(x<0)return 0;
    int n=0;
    while(x)p[n++]=x%10,x/=10;n--;
    memset(d,0,sizeof d);
    for(int i=0;i<=n;i++)
    {
        if(i==0)
        {
            for(int j=0;j<=9;j++)
            {
                d[i][j][200+j][0].sum=j;
                d[i][j][200+j][0].cnt=1;
                d[i][j][200-j][1].sum=j;
                d[i][j][200-j][1].cnt=1;
            }
            continue;
        }
        for(int j=0;j<=9;j++)
        {
            for(int k=0;k<=9;k++)
            for(int sum=200-9*i;sum<=200+9*i;sum++)
            {
                (d[i][j][sum-j][1].sum+=d[i-1][k][sum][0].sum+d[i-1][k][sum][0].cnt*j%MOD*f[i]%MOD)%=MOD;
                (d[i][j][sum-j][1].cnt+=d[i-1][k][sum][0].cnt)%=MOD;

                (d[i][j][sum+j][0].sum+=d[i-1][k][sum][1].sum+d[i-1][k][sum][1].cnt*j%MOD*f[i]%MOD)%=MOD;
                (d[i][j][sum+j][0].cnt+=d[i-1][k][sum][1].cnt)%=MOD;
            }
        }
    }
    ll ans=0;
    for(int i=0;i<n;i++)
    {
        for(int j=1;j<=9;j++)(ans+=d[i][j][num][0].sum)%=MOD;
    }
    ll dig=0,tot=0;
    for(int i=n;i>=0;i--)
    {
        if(i==n)
        {
            for(int j=1;j<p[i];j++)(ans+=d[i][j][num][0].sum)%=MOD;
        }
        else
        {
            for(int j=0;j<p[i];j++)
            {
                (ans+=d[i][j][num-dig][(n-i)%2].sum)%=MOD;
                (ans+=d[i][j][num-dig][(n-i)%2].cnt*tot%MOD)%=MOD;
            }
        }
        if((n-i)%2==0)dig+=p[i];
        else dig-=p[i];
        (tot+=p[i]*f[i]%MOD)%=MOD;
    }
    return ans+(dig+200==num?tot:0);
}
int main()
{
    f[0]=1;
    for(int i=1;i<=19;i++)f[i]=f[i-1]*10%MOD;
    ll L,R,k;
    cin>>L>>R>>k;
    printf("%lld\n",(cal(R,k+200)-cal(L-1,k+200)+MOD)%MOD);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Mitsuha_/article/details/82152976
今日推荐