欢迎光临 ~|

Laijinyi

园龄:1年7个月粉丝:2关注:2

数位 dp 题

T1

Statement

任意相邻两个数字之差至少为 2 的正整数被称为 windy 数。给出 A,B(AB2×109),求 [A..B] 中有多少个 windy 数。

Solution

我们使用记忆化搜索实现。

f(i,x,a,b) 表示还有 i 位需要确定,上一位数字为 x,是否达到上限,是否不含前导 0 的方案数。

转移

int mx = a ? num[i] : 9, ans = 0;
for (int k = 0; k <= mx; k++)
if (abs(x - k) >= 2 || !b)
ans += dfs(i - 1, k, a&(k==mx), b|(k!=0));
f[i][x][a][b] = ans;

初值:-1

边界i = 0 时返回 1

答案dfs(n, 0, 1, 0)

最后用两个前缀相减得到答案。

T2

Statement

给定正整数 A101000)和 S5000),需要在 A 的数码之间添加若干个加号,使得得到的式子与 S 相等。问最少添加多少个加号。

Solution

  • num(i,j) 表示 A 中第 i 个数字到第 j 个数字组成的数.
  • n 表示 A 的长度,m 表示 S 的长度.

f(i,j) 表示后 i 位数字加起来等于 j 的最少加号数.

f(i,j)=mink=i+1min(n,i+2m1){f(k,jnum(i,k1))+1}

这里我们让新增的数的位数不超过 S,保证了复杂度;同时注意 jnum(i,k1) 需要大于 0.

注意到前导零的存在(如 1 + 0001 + 1),所以我们最多保留 m1 个连续的 0,并让 k 循环到 i+2m1

因为如果有多于 m1 个连续的 0,那么多出的 0 就不能与前面的数组合,就没用了;此时 k 最多需要循环到 i+2m1

初始 f(n,0)=0,其余设为 inf

时间复杂度 O(nmS).

T3

Statement

找一个数作为“支点”,两边的“力矩”相等的数称为“平衡数”。给出正整数 x,yxy1018),问 [x..y] 中有多少个“平衡数”。

Solution

由于两边力矩相等,令一边为正、一边为负,那么相加就是 0.

然后发现力矩最大为 18×9+17×9+..+1×9=1539,很小

无限制:

f(x,i,1/0) 表示 i 个数使得力矩为 x 的方案数,每个数 [0,9],其中第一个数能否为 0.

f(x,i,0)=j=09f(xij,i1,0),其中要求 xij0

f(x,i,1)=j=19f(xij,i1,0)

设这个数有 i 位,则方案数 =k=01539j=2i110×f(k,j1,1)×f(k,ij,0)

i=1 时方案数 =10

有限制:

设有 i 位待确定,这个数一共 n 位,每位数字分别为 ak

枚举支点 x 和力矩 y

方案数 =x=2n1y=pp+9×max(0,(xn+i)(xn+i+1)/2)f(yp,xn+i,0)f(y,nx,0)

其中 p 表示已知的数字在支点 x 下产生的力矩大小,即

p=j=1ni+1aj|xj|

xn+i0,令 f(yp,xn+i,0)=1

=======

答案加起来就行了

时间复杂度 O(18×1539+18×1539×18+18×18×1539)=O(1,024,974)

T4

Statement

cnt1(i) 表示二进制整数 i 中包含的数字 1 的个数。给定 N1015),求 i=1Ncnt1(i)modQ

Solution

不卡到上限

设有 i 位,选出 j 个 1,则 cnt1=j,有 (ij) 种选法,故乘 (ij)

所以 Ans=j=1ij(ij)modQ

卡到上限

设共 L 位,还有 i 位未确定(不包括当前),cnt(k) 表示前 k 位的 1 的数量

若当前已经卡到了上限,则继续向下一位计算(若选 1 则一定会卡到上限);

若当前选 0,则相似地,Ans=j=1i(cnt(Li1)+j)(ij)modQ

========

所有的 Ans 乘起来再 mod Q 即可,因为只有 15 位,直接暴力算都绰绰有余

我们发现一个问题:(ij) 可能会超过 long long 范围,此时将他 mod φ(Q) 即可

T5

Statement

一个数各相邻数位的下降、相等和上升用 \-/ 三个字符表示,然后将连续相同的字符缩写成一个,形成一个长度为 n100)的给定字符串,问 [A..B] 中有多少个数的波动关系缩写以后等于它。0AB10100,有 100 组数据。

Solution

数的长度限制为 mcmp(x,y) 表示数 x,y 之间的波动关系,ck 表示字符串从右往左第 k 位的波动关系,ak 表示该数从左往右第 k 个数码

f(i,x,j) 表示有 i 位,最高位为 x,对应给出字符串从右往左 j 个字符,的方案数

f(i,x,j)=y=09t,其中 j0

cmp(x,y)=cji>j+1 时,t=f(i1,y,j1)+f(i1,y,j)

cmp(x,y)=cji=j+1 时,t=f(i1,y,j1)

f(1,x,0)=1,i[1,9],其余初始为 0

无限制Ans=i=1m1j=19f(i,j,n)

有限制

g(i) 表示确定的前 i 位满足字符串从左往右的字符数,c 变成从左往右数.

i=0Ans=j=1ai+11f(m,j,n)

i=1Ans=j=0  cmp(ai,j)=c1ai+11f(mi,j,n1)+f(mi,j,n)

i>1g(i)>0 时,其中 j[0..ai+11]

  1. cmp(j,ai)=cg(i) 时:Ans=f(mi,j,ncg(i)+1)+f(mi,j,ncg(i))

  2. cmp(j,ai)=cg(i)+1 时:Ans=f(mi,j,ncg(i)1)+f(mi,j,ncg(i))

最后答案就是加起来. 然后前缀和相减.

复杂度 O(TnmB2),其中 B=10.

T6

Statement

一个数是“漂亮的”,当且仅当它能够被它的每个非零位整除。问 [L..R] 中有多少个数是“漂亮的”。1LR9×1018

Solution

每个数位 [0,9],观察到 lcm(1,2,..,9)=2520 极小,故枚举 lcm.

那么若一个数被 lcm 整除,则这个数是“漂亮的”.

f(i,j,k) 表示这个数有 i 位(含前导零),这个数 mod 2520=j,这个数的各数位 lcm=k,的个数

假设当前 f(i,j,k) 已知,规定 lcm(x,0)=x,我们用它向外更新:

f(i+1,(j+p)mod2520,lcm(k,p)) += f(i,j,k),其中 p[0..9]

f(1,p,p)=1p[0..9]),其余初始化为 0.

无限制:设 n 位,一起算:Ans=k=12520l=12520kf(n,lk,k)

有限制

设共 n 位,有 i 位已知,s(k) 表示前 k 位已知数码组成的数,l(k) 表示前 k 位已知数码的 lcm.

分开算:Ans=j=02519k=12520f(ni,j,k),且 j,k 满足 lcm[l(i),k] 整除 [s(i)×10ni+j]mod2520.

总的答案就把所有 Ans 加起来,然后用前缀和相减得到.

时间复杂度 O(nm2+mlogm+nm2)=O(nm2),其中 n 是数字长度,m=2520.

本文作者:Laijinyi

本文链接:https://www.cnblogs.com/laijinyi/p/18148220/Num-dps1

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   Laijinyi  阅读(38)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起