计算幸运数字的个数

我们称一个长度为n的数X(X= d1d2......dn, d1 != 0)为幸运数,当且仅当,对于所有的i \epsilon [1, \frac{n}{2}], 满足di != d(n+1-i),请问在[a, b]之间存在多少幸运数:

分析:

只需计算x<= b 以及< a分别有多少个幸运数即可。

对于数字b(假设b的位数是n, 每一位数字存在数据data[n]中,下标以1开始)

示例:

 b = 2999

则 n = 4, data = [-1, 2, 9, 9, 9]

则对于b需要求得分为4部分:

1. 所有一位数字中的幸运数 f(1) =9

2. 所有两位数字中的幸运数:f(2)= 81

3. 所有三位数字中的幸运数  f(3) =810

4. 1000-2999之间的幸运数

定义f(n) 为所有n位数中幸运数字个数,对于 1,2, 3 ,部分当数字为 n的时候 很容易有递推公式

f(n) = 9*(f(n-2)+f(n-4)*9+...+f(n-2^i)*9^(i-1) + f(0)*9^(n/2-1))*9, n>= 4,f(0) = 1, n 为偶数

简单理解就是 对于数字 d1d2......dn, d1和dn 都有 9 种取法,假设cnt(num) 是求num的数字个数,则

f(cnt(d1d2....dn)) = 9*9*(d2!= 0 的时候的个数+d2==0的个数)= A+B

A = f(cnt(d2...dn-1)

B = (d3!= 0 的时候的个数+d3==0的个数)以此内推

对于第四部分:

1000-2999之间

一个循环求得:

res = 0

i = 1, res+= (data[1]-1)*(A+B)

for i in range(2, n + 1):
    if(data[i]==0):
        break
    if(i <= (n // 2)):
        res += data[i] * f(n - 2 * i) * (9 ** (i + 1))
        continue
    if(n%2 == 1 and i == n//2 + 1):
        res += data[i]*(9**i)
        continue
    else:
        if(data[n+1-i] >= data[i]):
            res += data[i]*9**(n - i)
        else:
            res += (data[i]-1)*9**(n - i)

具体代码见下面(关于A+B的代码计算部分有待修改):

a, b = [int(x) for x in input().split()]
def f(n):
    if (n == 0):
        return 1
    if(n == 1):
        return 9
    if(n == 2):
        return 81
    if(n == 3):
        return 810
    else:
        return 81*(f(n-2)+f(n-4)*9)
def get_data(b):
    cnt = 0
    data = []
    while(b>0):
        data.append(b%10)
        b = b // 10
        cnt += 1
    data.append(-1)
    data.reverse()
    return (cnt, data)
def isluck(data, n):
    find = True
    for i in range(1, n // 2+1):
        if (data[i] == data[n + 1 - i]):
            find = False
            break
    return find

def count(n, data, b):
    res = 0
    if(n >= 4):
        res += (data[1]-1) * (f(n - 2) + f(n - 4) * 9) * 9
    if(n == 3):
        res += (data[1]-1) * (f(n - 2) + f(0)) * 9
    if(n == 2):
        res += (data[1] - 1)*9
    if(n == 1):
        res += data[0]
        return res
    for i in range(2, n + 1):
        if(data[i]==0):
            break
        if(i <= (n // 2)):
            res += data[i] * f(n - 2 * i) * (9 ** (i + 1))
            continue
        if(n%2 == 1 and i == n//2 + 1):
            res += data[i]*(9**i)
            continue
        else:
            if(data[n+1-i] >= data[i]):
                res += data[i]*9**(n - i)
            else:
                res += (data[i]-1)*9**(n - i)
    if(isluck(data, n)):
        res += 1
    for i in range(1, n):
        res += f(i)
    return res

cnt_b, data_b = get_data(b)
cnt_a, data_a = get_data(a-1)

res_b = count(cnt_b, data_b, b)
res_a = count(cnt_a, data_a, a-1)
print(res_b-res_a)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值