题目描述
#1033 : 交错和
时间限制:10000ms
单点时限:1000ms
内存限制:256MB
描述
给定一个数 x,设它十进制展从高位到低位上的数位依次是
a
0
,
a
1
,
.
.
.
,
a
n
−
1
a_0, a_1, ..., a_{n - 1}
a0, a1, ..., an − 1,定义交错和函数:
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) = a0 − a1 + a2 − ... + (−1)n − 1an − 1
例如:
f ( 3214567 ) = 3 − 2 + 1 − 4 + 5 − 6 + 7 = 4 f(3214567) = 3 - 2 + 1 - 4 + 5 - 6 + 7 = 4 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 \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(0 ≤ l ≤ r ≤ 1018, ∣k∣ ≤ 100)。
输出
输出一行一个整数表示结果,考虑到答案可能很大,输出结果模
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,l−1]的交错和。
所以问题转化为:如何求
[
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
)
<
b
i
t
s
(
x
)
]
\sum z[bits(z)==bits(x) 且z \le x] + \sum z[bits(z) < bits(x)]
∑z[bits(z)==bits(x)且z≤x]+∑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
则有
- 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_num−b)
- 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_num−b)
- 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=19p∗10bits_num−1∗C(True,bits_num−1,i−cross_value)+F(True,bits_num−1,i−cross_value)
- 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_num−1,i−cross_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;
}