同时考验对状压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 = ;
const int MAXM = ;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9+;
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 = ; int w = ; register char c = getchar();
for(; c ^ '-' && (c < '' || c > ''); c = getchar());
if(c == '-') w = -, c = getchar();
for(; c >= '' && c <= ''; c = getchar()) x = (x<<) + (x<<) + c - ''; return x * w;
}
char s[];
int T,m,len,digit[],num[],e[],dp[][][];
int dfs(int cur, int sta, int mo, bool lim){
if(cur == len){
if(mo== && lim==){
return ;
}
else{
return ;
}
}
int& a = dp[sta][mo][lim];
if(a != -) return a;
a = ;
for(int i = ; i < len; ++i){
if(lim && num[i] > e[cur]) break;
if(sta & (<<i)) continue;
if(i== || num[i]!=num[i-] || (sta & (<<(i-)))){
digit[cur] = num[i];
a = (a + dfs(cur+, sta|(<<i), (mo*+num[i])%m, lim&(num[i]==e[cur]))) % MOD;
}
}
return a;
}
int main(){
scanf("%d",&T);
while(T--){
memset(dp,-,sizeof(dp));
memset(digit,,sizeof(digit));
scanf("%s",s);
scanf("%d",&m);
len = strlen(s);
for(int i = ; i < len; ++i){
e[i] = s[i] - '';
num[i] = e[i];
}
sort(num,num+len);
printf("%d\n",dfs(,,,));
}
return ;
}

「Algospot」津巴布韦ZIMBABWE的更多相关文章

  1. 「Algospot」龙曲线DRAGON

    一道考验思维的好题,顺便总结求第k大问题的常规思路: 传送门:$>here<$ 题意 给出初始串FX,每分形一次所有X替换为X+YF,所有Y替换为FX-Y.问$n$代字符串第$p$位起长度 ...

  2. 「Algospot」量化QUANTIZE

    一道不难的DP题,主要是为了总结这类最优化题的思路:同时还学到了一个新操作 传送门:$>here<$ 题意 给出一个长度为$N$的序列,要求最多使用s个数字进行量化(有损压缩),即代替原数 ...

  3. 「译」JUnit 5 系列:条件测试

    原文地址:http://blog.codefx.org/libraries/junit-5-conditions/ 原文日期:08, May, 2016 译文首发:Linesh 的博客:「译」JUni ...

  4. 「译」JUnit 5 系列:扩展模型(Extension Model)

    原文地址:http://blog.codefx.org/design/architecture/junit-5-extension-model/ 原文日期:11, Apr, 2016 译文首发:Lin ...

  5. JavaScript OOP 之「创建对象」

    工厂模式 工厂模式是软件工程领域一种广为人知的设计模式,这种模式抽象了创建具体对象的过程.工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题. function createPers ...

  6. 「C++」理解智能指针

    维基百科上面对于「智能指针」是这样描述的: 智能指针(英语:Smart pointer)是一种抽象的数据类型.在程序设计中,它通常是经由类型模板(class template)来实做,借由模板(tem ...

  7. 「JavaScript」四种跨域方式详解

    超详细并且带 Demo 的 JavaScript 跨域指南来了! 本文基于你了解 JavaScript 的同源策略,并且了解使用跨域跨域的理由. 1. JSONP 首先要介绍的跨域方法必然是 JSON ...

  8. 「2014-5-31」Z-Stack - Modification of Zigbee Device Object for better network access management

    写一份赏心悦目的工程文档,是很困难的事情.若想写得完善,不仅得用对工具(use the right tools),注重文笔,还得投入大把时间,真心是一件难度颇高的事情.但,若是真写好了,也是善莫大焉: ...

  9. 「2014-3-18」multi-pattern string match using aho-corasick

    我是擅(倾)长(向)把一篇文章写成杂文的.毕竟,写博客记录生活点滴,比不得发 paper,要求字斟句酌八股结构到位:风格偏杂文一点,也是没人拒稿的.这么说来,arxiv 就好比是 paper 世界的博 ...

随机推荐

  1. [转]Have a query in Blue prism coding stage and collection stage.

    本文转自:https://www.rpaforum.net/threads/have-a-query-in-blueprism-coding-stage-and-collection-stage.48 ...

  2. C# T4 模板 数据库实体类生成模板(带注释,娱乐用)

     说明:..,有些工具生成实体类没注释,不能和SqlServer的MS_Description属性一起使用,然后照着网上的资源,随便写了个生成模板,自娱自乐向,其实卵用都没有参考教程    1.htt ...

  3. h5与c3权威指南笔记--css3新属性选择器

    [att*=val] 选择所有att属性值中包含val的.只要包含val值,不论val值在属性值的前面还是中间还是后面~ <style> div[class*=div]{ color: r ...

  4. App隐私条款

    欢迎光临本app,请您仔细阅读以下条款,如果您对本协议的任何条款表示异议,您可以选择不使用本app:进入本app则意味着您将同意遵守本协议下全部规定,并完全服从于app开发者的统一管理. 第一章 总则 ...

  5. 章节十一、1-Junit介绍

    一.Junit是一个开源的测试框架,在selenium的jar包中,不需要单独安装和搭建环境 二.@BeforeClass:当在方法上加了这个注解的话,这个方法会在这个类的第一个test方法之前运行. ...

  6. Nginx设置Https反向代理,指向Docker Gitlab11.3.9 Https服务

    目录 目录 1.GitLab11.3.9的安装 2.域名在阿里云托管,申请免费的1年证书 3.Gitlab 的 https 配置 4.Nginx 配置 https,反向代理指向 Gitlab 配置 目 ...

  7. 数据文件实时同步(rsync + sersync2)

    因近期项目需求,需要同步云端服务器的数据给**方做大数据分析. 思路: 起初只要数据同步,准备开放数据采集接口.但实时性较差,会有延迟. 故而寻觅各种解决方案,最终确定使用 rsync 进行文件同步, ...

  8. VS2017的MVC和Angular联合开发的配置文件作用

    在通过MVC和Angular联合开发项目时,项目里有几个重要的配置文件,下面列出这几个配置文件的分析和比较: 主要配置文件有appsettings.json,tsconfig.json,package ...

  9. ASP.NET学习笔记 —— 一般处理程序之图片上传

    简单图片上传功能目标:实现从本地磁盘读取图片文件,展示到浏览器页面.步骤:(1). 首先创建一个用于上传图片的HTML模板,命名为ImageUpload.html: <!DOCTYPE html ...

  10. 【记录】使用在线KMS激活win10系统

    摘要 网上一些激活工具可能捆绑了木马.病毒.使用激活工具有风险.使用在线KMS来激活系统则没有这个风险.(自测至发布日期仍然可用) (有能力的请支持正版windows系统) 将kms服务器地址设置为k ...