博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
uoj140 【UER #4】被粉碎的数字
阅读量:5146 次
发布时间:2019-06-13

本文共 1131 字,大约阅读时间需要 3 分钟。

看起来就像是数位\(\rm dp\)

不妨从竖式乘法的角度来考虑这个问题

为了方便处理进位,我们得从低位向高位填数

\(dp[i][0/1][j][p][t]\)表示填到了第\(i\)位,卡不卡上界,\(f(x)=j\)\(f(k\times x)=p\)(不计算最高位),需要向最高位进\(t\)\(x\)有多少个

这里的卡上界比较奇怪,如果这一位上填的数大于\(R\)这一位上的数,那么就一定卡了上界,如果小于这一位上的数,那么就一定不卡上界,如果和原来的数相等,那么就继续之前的状态

所以这个\(0/1\)就表示后面的\(i\)为和\(R\)\(i\)位的大小关系,如果填的数大于\(R\)\(i\)为,那么这个状态就是\(1\);否则就是\(0\)

至于转移,就比较简单,我们枚举这一位上填什么数\(y\),那么对于\(x\),数位和增加了\(y\),对于\(k\times x\),这一位上直接来一个乘法是\(k\times y\),还有之前的进位\(t\),于是就是\((k\times y+t)\% 10\),新的进位就是\((k\times y+t)/10\)

但是这样我们填到\(R\)的最高位之后可能还有一些进位没有处理,于是再往前多处理\(3\)位把进位处理完

最后的答案就是\(\sum_{i}dp[\lg_{R}][0][i][i][0]\),即\(x\)的数位和等于\(f(k\times x)\)的情况,但是这样多了一维非常难受,考虑的最后只要求\(j=p\),所以我们直接把\(j-p\)看成一维状态就好了

代码

#include
#define re register#define LL long longLL dp[25][2][1000][500];int m,w,a[25],M=250;LL n;inline void split(LL x) { while(x) a[++w]=(x%10),x/=10;}int main() { scanf("%lld%d",&n,&m); dp[0][0][0][M]=1; split(n); for(re int i=0;i
a[i+1]][(k+t*m)/10][p+t-(k+t*m)%10]+=dp[i][j][k][p]; } printf("%lld\n",dp[w+3][0][0][M]-1); return 0;}

转载于:https://www.cnblogs.com/asuldb/p/11455315.html

你可能感兴趣的文章
浅谈C#4 Dynamic
查看>>
不规则button,不规则view的创建
查看>>
PHP错误
查看>>
2014年3月份第4周51Aspx源码发布详情
查看>>
2014年6月份第3周51Aspx源码发布详情
查看>>
如何查看通过系统命令查看ORA错误信息?
查看>>
bat
查看>>
Unity XML
查看>>
jQuery Mobile 1.2 RC2 发布
查看>>
线程、进程同步
查看>>
0x16 Trie
查看>>
数学趣题_父亲分羊
查看>>
MySQL MyISAM与Innodb优化方案比较
查看>>
关联查询
查看>>
清除浮动业界常用的方法
查看>>
作业 3 应用分支与循环结构解决问题 查询水果单价
查看>>
WinCE学习系列(1)——在VS2008的环境下安装WinCE 5.0仿真模拟器
查看>>
[USACO 07DEC]Best Cow Line, Gold
查看>>
JavaScript世界的一等公民 - 函数
查看>>
BZOJ 1257 [CQOI2007]余数之和sum(分块)
查看>>