hicoder #1033 交错和

hicoder #1033 交错和

题目描述

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

f ( x )   =   a 0   −   a 1   +   a 2   −   . . .   +   ( − 1 ) n   −   1 a n   −   1 f(x) = a_0 - a_1 + a_2 - ... + (-1) ^{n - 1}a_{n - 1} f(x)=a0a1+a2...+(1)n1an1

例如:

f ( 3214567 )   =   3   −   2   +   1   −   4   +   5   −   6   +   7   =   4 f(3214567) = 3 - 2 + 1 - 4 + 5 - 6 + 7 = 4 f(3214567)=32+14+56+7=4

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

∑ x = l r [ f ( x ) = k ] x \sum_{x=l}^{r}[f(x)=k]x x=lr[f(x)=k]x

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

输出
输出一行一个整数表示结果,考虑到答案可能很大,输出结果模 1 0 9   +   7 10^9 + 7 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

问题解析

要求 [ l , r ] [l,r] [l,r]之前交错和为 k k k的数之和,只需求 [ 0 , r ] [0,r] [0,r]的交错和减去 [ 0 , l − 1 ] [0,l-1] [0,l1]的交错和。
所以问题转化为:如何求 [ 0 , x ] [0,x] [0,x]的交错和,不妨设 G ( x , v a l u e ) G(x,value) G(x,value) [ 0 , x ] [0,x] [0,x]中交错和为 v a l u e value value的数之和。
对于 G ( x , v a l u e ) G(x, value) G(x,value),设 b i t s ( x ) bits(x) bits(x)为x的十进制位数,显然有,
∑ z [ b i t s ( z ) = = b i t s ( x ) 且 z ≤ x ] + ∑ z [ b i t s ( z ) &lt; b i t s ( x ) ] \sum z[bits(z)==bits(x) 且z \le x] + \sum z[bits(z) &lt; bits(x)] z[bits(z)==bits(x)zx]+z[bits(z)<bits(x)]

F ( h i g h e s t _ z e r o _ f l a g , b i t s _ n u m , c r o s s _ v a l u e ) F(highest\_zero\_flag, bits\_num, cross\_value) F(highest_zero_flag,bits_num,cross_value)为满足下列条件的数 z z z之和, C ( h i g h e s t _ z e r o _ f l a g , b i t s _ n u m , c r o s s _ v a l u e ) C(highest\_zero\_flag, bits\_num, cross\_value) C(highest_zero_flag,bits_num,cross_value) z z z的个数:

  • z z z的最高位可为 0 0 0 当且仅当 h i g h e s t _ z e r o _ f l a g highest\_zero\_flag highest_zero_flag为True,否则最高位不能为 0 0 0
  • b i t s ( z ) = b i t s _ n u m bits(z) = bits\_num bits(z)=bits_num
  • f ( z ) = c r o s s _ v a l u e f(z) = cross\_value f(z)=cross_value

则有

  1. F ( T r u e , b i t s _ n u m , c r o s s _ v a l u e ) = ∑ b = 1 b i t s _ n u m F ( F a l s e , b , c r o s s _ v a l u e ∗ ( − 1 ) b i t s _ n u m − b ) F(True,bits\_num,cross\_value) = \sum_{b=1}^{bits\_num} F(False,b,cross\_value*(-1)^{bits\_num-b}) F(True,bits_num,cross_value)=b=1bits_numF(False,b,cross_value(1)bits_numb)
  2. C ( T r u e , b i t s _ n u m , c r o s s _ v a l u e ) = ∑ b = 1 b i t s _ n u m C ( F a l s e , b , c r o s s _ v a l u e ∗ ( − 1 ) b i t s _ n u m − b ) C(True,bits\_num,cross\_value) = \sum_{b=1}^{bits\_num} C(False,b,cross\_value*(-1)^{bits\_num-b}) C(True,bits_num,cross_value)=b=1bits_numC(False,b,cross_value(1)bits_numb)
  3. F ( F a l s e , b i t s _ n u m , c r o s s _ v a l u e ) = ∑ i = 1 9 p ∗ 1 0 b i t s _ n u m − 1 ∗ C ( T r u e , b i t s _ n u m − 1 , i − c r o s s _ v a l u e ) + F ( T r u e , b i t s _ n u m − 1 , i − c r o s s _ v a l u e ) F(False,bits\_num,cross\_value)= \sum_{i=1}^{9} p * 10^{bits\_num-1}*C(True,bits\_num-1,i-cross\_value) + F(True,bits\_num-1,i-cross\_value) F(False,bits_num,cross_value)=i=19p10bits_num1C(True,bits_num1,icross_value)+F(True,bits_num1,icross_value)
  4. C ( F a l s e , b i t s _ n u m , c r o s s _ v a l u e ) = ∑ i = 1 9 C ( T r u e , b i t s _ n u m − 1 , i − c r o s s _ v a l u e ) C(False,bits\_num,cross\_value) = \sum_{i=1}^{9} C(True,bits\_num-1,i-cross\_value) C(False,bits_num,cross_value)=i=19C(True,bits_num1,icross_value)

其中每步加法乘法都应该模 1 0 9 + 7 10^9+7 109+7以避免溢出。

代码

#include <stdio.h>
#include <stdlib.h>

#define MAX_B     20
#define MOD_VALUE (1000000000+7)
#define TRUE      1
#define FALSE     0
long long l,r;
int k;

typedef struct {
  long long cross_sum;
  long long count;
}node_st;

long long base_headers[MAX_B] = {0};

node_st dp_list[MAX_B][201][2];

int number_list[MAX_B];
int number_list_length = 0;

void get_number_list(long long number )
{
    number_list_length = 0;
    do
    {
        number_list[number_list_length++] =  number % 10;
        number                            /= 10;
    }while(number!=0);
    for(int i = 0; i < number_list_length/2;i++)
    {
        int tmp = number_list[i];
        number_list[i] = number_list[number_list_length-1-i];
        number_list[number_list_length-1-i] = tmp;
    }
}

void init_dp()
{
    for(int i = 0;i < MAX_B;i++)
    {
        for(int j = 0; j < 201;j++)
        {
            dp_list[i][j][0].count = 0;
            dp_list[i][j][0].cross_sum = -1;
            dp_list[i][j][1].cross_sum = -1;
            dp_list[i][j][1].count = 0;
        }
    }
}

int max_value_of_bits( int bit_num )
{
    return 9 * (bit_num + 1) / 2;
}

int min_value_of_bits( int bit_num, int highest_zero_flag )
{
    if(bit_num <= 1)
    {
        return 0;
    }
    return ((highest_zero_flag==TRUE)?0:1) + bit_num / 2 * -9;
}

void get_parameters()
{
    scanf("%lld %lld %d",&l,&r,&k);
}

void initial_base()
{
    base_headers[0] = 1;
    for(int i = 1; i < MAX_B;i++)
    {
        base_headers[i] = (base_headers[i-1]*10)%MOD_VALUE;
    }
}

node_st dp_func(int highest_zero_flag, int bit_nums, int value)
{
    node_st result = {0,0};
    if(bit_nums == 0)
    {
        result.cross_sum = 0;
        result.count = (value==0)?1:0;
        return result;
    }
    if(bit_nums == 1)
    {
        if((value <= 9) && (value >= 0))
        {
            result.cross_sum = value;
            result.count     = 1;
        }
        return result;
    }
    if((value < min_value_of_bits(bit_nums,highest_zero_flag)) || (value > max_value_of_bits(bit_nums)))
    {
        return result;
    }
    if(dp_list[bit_nums][value+100][highest_zero_flag].cross_sum > -1)
    {
        return dp_list[bit_nums][value+100][highest_zero_flag];
    }

    result.cross_sum = 0;
    result.count = 0;
    if(highest_zero_flag == TRUE)
    {
        int current_value = value;
        for(int i = bit_nums;i > 0;i--)
        {
            node_st tmp = dp_func(FALSE,i,current_value);
            result.cross_sum = (result.cross_sum + tmp.cross_sum) % MOD_VALUE;
            result.count = ( result.count + tmp.count ) % MOD_VALUE;
            current_value *= -1;
        }
    }
    else
    {
        for(int i = 1;i < 10;i++)
        {
            long long current_prefix = i * base_headers[bit_nums-1] % MOD_VALUE;
            node_st tmp = dp_func(TRUE,bit_nums-1,i-value);
            if(tmp.count > 0)
            {
                result.cross_sum = (result.cross_sum + tmp.cross_sum)%MOD_VALUE;
                long long t_ = current_prefix * tmp.count % MOD_VALUE;
                result.cross_sum = (result.cross_sum + t_) % MOD_VALUE;
                result.count = ( result.count + tmp.count ) % MOD_VALUE;
            }
        }
    }
    dp_list[bit_nums][value+100][highest_zero_flag] = result;
    return result;
}

int self_check(int value)
{
    int cross_sum = 0;
    for(int i = 0; i < number_list_length;i++)
    {
        int factor = (i%2==0)?1:-1;
        cross_sum += factor * number_list[i];
    }
    return (cross_sum == value)?TRUE:FALSE;
}

long long get_cross_sum(long long number, int value )
{
    if(number < 10)
    {
        return (value <= number && value >=0 )?value:0;
    }
    get_number_list( number );
    long long cross_sum = 0;
    for(int bit_num = 1; bit_num < number_list_length;bit_num++)
    {
        node_st tmp = dp_func(FALSE,bit_num,value);
        cross_sum = (cross_sum + tmp.cross_sum)%MOD_VALUE;
    }
    long long prefix = 0;
    int rest_value = value;
    for(int i = 0; i < number_list_length;i++)
    {
        int factor = (i%2==0)?1:-1;
        int rest_bit_num = number_list_length - 1 - i;
        for(int j = (i==0)?1:0; j < number_list[i];j++)
        {
            int current_value = (rest_value - factor * j) * factor * -1;
            int current_prefix = (prefix * 10 + j)* base_headers[rest_bit_num] % MOD_VALUE;
            node_st tmp = dp_func(TRUE,rest_bit_num,current_value);
            if(tmp.count > 0)
            {
                cross_sum = (cross_sum + tmp.cross_sum)%MOD_VALUE;
                long long t_ = current_prefix * tmp.count % MOD_VALUE;
                cross_sum = (t_ + cross_sum)%MOD_VALUE;
            }
        }
        prefix = prefix * 10 + number_list[i];
        rest_value = rest_value - factor * number_list[i];
    }
    if(self_check(value)==TRUE)
    {
        cross_sum = (cross_sum + number)%MOD_VALUE;
    }

    return cross_sum;
}

int main()
{
    get_parameters();
    init_dp();
    initial_base();
    printf("%lld\n",(get_cross_sum(r,k)-get_cross_sum(l-1,k)+MOD_VALUE)%MOD_VALUE);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值