同时考验对状压DP和数位DP的理解;

传送门:$>here<$

题意

给出一个数字$e$,现在对$e$通过$m$进行变换得到$x$;变换的要求是:1.只能改变原数字$e$各个数位的顺序(可以有前导零) 2.$x$是$m$的倍数 3. $x<e$

问$x$有几种取值满足?

数据范围:$e \leq 10^14, m \leq 20$

Solution

DFS怎么做是关键

这道题如果使用DFS,那么大体思路就是枚举每一位填放什么数字。

那么需要一个数组(状压)在此过程中来记录还可以用哪些数字。这个地方不要想太多,我起初的思路刚开始统计一格数组代表0~9每个数字有几个,再依次减。然而这样麻烦,而且无法状压。一个直接的思路是直接用一个布尔数组表示原数组的每一位是否被用掉。

光这样是不行的,我们忘记考虑重复问题了。即$e=422$时,枚举每一位填什么时程序会把每个数字看成不同的,也就会出现$224,242,224,242$四种情况。

解决重复问题

如果按照我刚开始的思路把0~9各位统计出来就没这样的问题了。于是考虑能不能在状压的情况下也能达成这种效果。把$e$中各位进行排序得到$num$数组。这样的话,每当我使用一个数字的时候,先去检查在它之前的相同数字是否已被使用完——相当于把每种数字弄成一个栈,每次只能取栈顶。

转化为程序语言,就是满足一下三个条件中的一个:

1. 当前数字是$num$中的首个(特判第一个数字的栈顶)

2. 当前数字与前面那个数字不同(还未使用过的某个数字的栈顶)

3. 当前数字前面的那个已被用过(使用过的某个数字的栈顶)

目前为止,复杂度是阶乘

与数位DP相结合

找到刚才问题中的子结构——当还有哪些数字可以用确定时,只要知道之前数字的大小以及模m的情况即可了。

所谓数字的大小,就是在搜索的过程中保证搜出来的结果要小于e。之前学数位DP的时候已经强调过了,这也是数位DP的一个精髓思想:如果先前的数字已经较e的高位较小了,那么后面的数字可以任意填(无论如何不会超出e)。如果之前刚好与e一样,那么后面的依然要小心不超出。

透过题解看本质

状压解决顺序问题

当数据范围是十几,需要解决顺序问题时,往往采用状压

关于题中的重复问题

这题相较于一般的数位DP在于能使用的数的限制。却又要保证不重复,因此保证数字像栈一样使用的思路很重要,需要反复琢磨吧……

my code

代码的细节也是个大问题,严格区分cur和i——一个是递归中指示第几层的变量,一个是循环变量。

/*By DennyQi 2018*/
#include <cstdio>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 10010;
const int MAXM = 20010;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9+7;
inline int Max(const int a, const int b){ return (a > b) ? a : b; }
inline int Min(const int a, const int b){ return (a < b) ? a : b; }
inline int read(){int x = 0; int w = 1; register char c = getchar();for(; c ^ '-' && (c < '0' || c > '9'); c = getchar());if(c == '-') w = -1, c = getchar();for(; c >= '0' && c <= '9'; c = getchar()) x = (x<<3) + (x<<1) + c - '0'; return x * w;
}
char s[300];
int T,m,len,digit[300],num[300],e[300],dp[40010][30][2];
int dfs(int cur, int sta, int mo, bool lim){if(cur == len){if(mo==0 && lim==0){return 1;}  else{return 0;}}int& a = dp[sta][mo][lim];if(a != -1) return a;a = 0;for(int i = 0; i < len; ++i){if(lim && num[i] > e[cur]) break;if(sta & (1<<i)) continue;if(i==0 || num[i]!=num[i-1] || (sta & (1<<(i-1)))){digit[cur] = num[i];a = (a + dfs(cur+1, sta|(1<<i), (mo*10+num[i])%m, lim&(num[i]==e[cur]))) % MOD;}}return a;
}
int main(){scanf("%d",&T);while(T--){memset(dp,-1,sizeof(dp));memset(digit,0,sizeof(digit));scanf("%s",s);scanf("%d",&m);len = strlen(s);for(int i = 0; i < len; ++i){e[i] = s[i] - '0';num[i] = e[i];}sort(num,num+len);printf("%d\n",dfs(0,0,0,1));}return 0;
}

转载于:https://www.cnblogs.com/qixingzhi/p/10352529.html

「Algospot」津巴布韦ZIMBABWE相关推荐

  1. 如何直观地理解「协方差矩阵」?

    如何直观地理解「协方差矩阵」? Xinyu Chen Urban Traffic Data Analytics 372 人赞同了该文章 协方差矩阵在统计学和机器学习中随处可见,一般而言,可视作方差和协 ...

  2. 消除左递归实验代码_「leetcode」108. 构造二叉搜索树【递归】【迭代】详解!

    构造二叉搜索树,一不小心就平衡了 ❞ 108.将有序数组转换为二叉搜索树 将一个按照升序排列的有序数组,转换为一棵高度平衡二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树 ...

  3. 不带头节点的链表有哪些缺点_23张图!万字详解「链表」,从小白到大佬!

    链表和数组是数据类型中两个重要又常用的基础数据类型. 数组是连续存储在内存中的数据结构,因此它的优势是可以通过下标迅速的找到元素的位置,而它的缺点则是在插入和删除元素时会导致大量元素的被迫移动,为了解 ...

  4. 一位老码农的分享:一线程序员该如何面对「中年危机」?

    如果这是第二次看到我的文章,欢迎文末扫码订阅我个人的公众号(跨界架构师)哟~   本文长度为2728字,建议阅读8分钟. 坚持原创,每一篇都是用心之作- 先来聊一下这个问题的背景吧. 前两天有小伙伴问 ...

  5. 机器人 Ameca「苏醒」瞬间逼真到令人恐惧,网友纷纷惊叹……

    整理 | 禾木木 出品 | AI科技大本营(ID:rgznai100) 近日,国内外网友都被一段机器人「苏醒」的视频惊讶到. 视频开始时,机器人似乎已经睡着,眼睛闭着,头部略微向下倾斜.随着肩膀的伸展 ...

  6. AI 复活「她」! GPT-3 帮美国小哥复刻逝去未婚妻,但又夺走她……

    整理 | 禾木木 出品 | AI科技大本营(ID:rgznai100) 今年 7 月,一名33岁的美国小哥 Joshua Barbeau 在未婚妻去世后,根据她在 Facebook 和 twitter ...

  7. OpenAI 以 10 亿美元出售「灵魂」,网友热评不再「Open」

    编译 | 禾木木 出品 | AI科技大本营(ID:rgznai100) OpenAI 如何以 10 亿美元的价格出售其灵魂:GPT-3 和 Codex 背后的公司并不像它声称的那样开放. 当金钱成为障 ...

  8. 「软件」2.0时代已经到来,你需要这样的开发工具

    互联网催生了软件的繁荣,而在AI浪潮的推动下,软件正在朝着更「智能」的方向发展,也就是「软件2.0」时代.「软件2.0」其实就是神经网络,也就是这一波AI浪潮的基石. 在「软件1.0」时代,程序员用J ...

  9. 嵌入式开发「坑」太多?MathWorks 高级工程师教你 debug

    文/ 朱雪妍 据博思数据发布的<2018-2023年中国嵌入式软件行业市场发展现状调研与投资趋势前景分析报告>表明:2018年上半年我国嵌入式系统软件收入达4240.2亿元,累计增长6.6 ...

最新文章

  1. eclipse提示jre_给新手 Java 开发者的 7 点提示 | Linux 中国
  2. c#.net连接access操作类(转)
  3. adb shell 小米手机_如何在Android手机上进行自动化测试
  4. EL表达式的11个内置对象
  5. 基于java SSM springboot景区行李寄存管理系统设计和实现
  6. 【分享】搭建域环境实现主域和文件服务器的热备冗余
  7. c/c++这么难学,那么学会了究竟有多牛X呢?
  8. 安卓案例:绑定和解绑服务
  9. 【Kafka】kafka 客户端 控制台 flink 都无法消费的情况
  10. Python+matplotlib绘图使用Latex引擎渲染坐标轴刻度文本上标
  11. 目前最流行的前端开发框架
  12. SQLyog注册激活码
  13. AMS1117-5.0-ASEMI低压差线性稳压IC详细解析
  14. matlab大地坐标与经纬度转换,如何把经纬度转化为大地坐标
  15. 精品软件-每日更新2013-1112
  16. 2017 寒假作业 (一) 随笔
  17. 校招,面试,学习路线,这个编程学习网站,我爱了
  18. 产品经理–是否具有战略意义?
  19. Hadoop 3.x主要变化(相对于Hadoop 2.x)
  20. Android Crash:Bad notification for startForeground

热门文章

  1. Keepalived实现双机热备
  2. wcf分布式构架集群案例解决方案
  3. 关于无法获取客户端IP地址
  4. C#的COM接口定义细则
  5. Flutter GetX 状态管理 使用入门 程序计数器 (二)
  6. java基础—IO流——将一些字符写入到指定硬盘上的目录中去:
  7. JavaScript设计模式返璞归真
  8. 矩阵相乘Java版(第一个java程序)
  9. Django--工程搭建
  10. Linux——通配符