jzoj4467 数字方阵

这题坑了我将近5个小时!!!

题目大意:

有一个无限大的平板
我们定义A[i,j]表示平板上第i行第j列的数字:
1. A[i,1] = i,
2. A[i,j] = A[i,j-1] + Rev( A[i,j-1] ), 其中Rev(x)表示x在10进制下的翻转,例如Rev(213) = 312, Rev(406800) = 008604 = 8604 。
Q个问题,给你两个整数A和B,请问区间[A,B]的数字总共在平板上出现了多少次?
(1 <= A,B <= 10^10

解法

首先我们观察一个6位的数与他的反转的和:

不难发现,除第一位a1无法为0外,ai的取值在0..9之间,且结果的位是对称的,也就是说,ai+aj的取值在0+0~9+9之间,即0~18共19个数,那我们可以很愉快的得出,当x≤10^10时,x+rev(x)约有19^5个结果。

由于时限是5s,我们可以先枚举a1+an,a2+an-1,,,,an+a1这5个数,然后将他们组合、算出所有可能的数在第二列出现的次数,因为平板无限大所以第一列会有所有可能的x
组合出的数的次数就是这5个数的方案数的乘积,比如2的方案数有[0,2][1,1][0,2]共3个。
然后我们用hash存下非第一列出现的数,将所有数排序,然后对于一个x就去贡献x+rev(x)的方案数,最后做一个前缀和处理询问就可以了。

需要注意的地方

  1. 要注意a1+an如果是<10的,那么要将a1=0的方案删除!!
  2. 如果枚举出来的数是奇数位,那么最中间那一位的方案数只有一而且必须要是偶数,因为是两个同样的数相加得到的。
  3. hash表的key要开素数,假设你开了一个mo=xy,那么要是要hash的数的约数与x或y有关系的话那冲突的概率就会增加,所以key最好是开素数亲测开素数2000+ms,不开素数5000+ms
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值