CF401D Roman and Numbers
题意:
将n(n<=10^18)的各位数字重新排列(不允许有前导零) 求 可以构造几个mod m等于0的数字
分析:
状态压缩
状态:
设f[s][k]表示对于选择数字组合的s来说,%m等于k的排列数量。
第一维大小:2^18 第二维大小:100
阶段:
对于s的选择的枚举。s直接从1枚举到1<<(cnt+1) 这样到了s(n)时,所有能转移到s(n)的状态都已经处理完毕。不会有后效性。
由于对于1~n的所有排列,可以考虑是从中选择任意的n-1个数的所有排列,再在最末尾选上剩余的一个数。 所以之后的s(n)所能转移到的最优解,都是与s(n)有关系的(都是通过在s(n)末尾接上一个数转移的),所以满足最优子结构性质。
转移:
对于给定的s,它的18位二进制表示中的每一位是0或者是1表示这一位上的数选择或者不选择。 我们将i从0循环到cnt,(cnt=n的位数-1)想要枚举的是s的每一位1,即枚举出来这个s所选的所有的数的位置,也就知道了所选择的数。
再枚举一下余数j,这样,可以写出这样的状态转移方程:
f[s][(j x 10+w[i])%m]+=f[s^(1<<i)][j]
意义是:每一位的选择都是通过这一位不选择的剩下状态,再把这一位放在末尾组成状态s转移的。
设之前的数为X,X=km+j;
选择了w[i]之后,X=10km+10j+w[i]; 余数就变成了:(10j+w[i])%m
然而有一个缺陷。。。
在于对于有重复数字时,会将一个状态转移从“其实是同一个组合”转移多遍,
举例:n=221 111会从101 转移一次,还会从011转移一次。然而这两个组合其实都是2、1,所以会算重。
所以可以在最后的时候进行多重集合的处理。 也可以每次枚举的时候,判断这一位的值是否之前已经处理过了。
if(vis[w[i]]) continue;
代码:
#include<bits/stdc++.h>
#define ll long long
const int maxs=(<<)+;
const int maxn=;
using namespace std;
int cnt=-,w[],m;
ll f[maxs][maxn],n;
bool vis[];
int main()
{
for(cin>>n>>m;n;n/=)
w[++cnt]=n%;
f[][]=;
for(int s=;s<<<cnt+;s++)
{ memset(vis,,sizeof vis);//注意清空
for(int i=;i<=cnt;i++)
{
if(s==(<<i)&&!w[i]) break;//去掉前导零
if(!(s&(<<i))||vis[w[i]]) continue;//判断是否选择了这一位,并且跳过已经处理过删去w[i]之后转移的情况。
vis[w[i]]=;//标记处理过这个数了。
for(int j=;j<m;j++)
f[s][(j*+w[i])%m]=(f[s][(j*+w[i])%m]+f[s^(<<i)][j]);
}
}
cout<<f[(<<cnt+)-][];//f[11..1][0]
return ;
}
CF401D Roman and Numbers的更多相关文章
- CF401D Roman and Numbers 状压DP
CF401D 题意翻译 将n(n<=10^18)的各位数字重新排列(不允许有前导零) 求 可以构造几个mod m等于0的数字 题目描述 Roman is a young mathematicia ...
- Codeforces Round #235 (Div. 2) D. Roman and Numbers (数位dp、状态压缩)
D. Roman and Numbers time limit per test 4 seconds memory limit per test 512 megabytes input standar ...
- Codeforces Round #235 (Div. 2) D. Roman and Numbers(如压力dp)
Roman and Numbers time limit per test 4 seconds memory limit per test 512 megabytes input standard i ...
- Codeforces Round #235 (Div. 2) D. Roman and Numbers 状压dp+数位dp
题目链接: http://codeforces.com/problemset/problem/401/D D. Roman and Numbers time limit per test4 secon ...
- 题解-Roman and Numbers
题解-Roman and Numbers 前置知识: 数位 \(\texttt{dp}\) </> \(\color{#9933cc}{\texttt{Roman and Numbers} ...
- CF401D 【Roman and Numbers】
题意将n(n<=10^18)的各位数字重新排列(不允许有前导零) 求 可以构造几个mod m等于0的数字解法状压f[S][k] 表示选用的位数集合为S,mod m 为k的方案数注意不能有前导 ...
- Codeforces 401D Roman and Numbers
题目大意 Description 给定一个数 N(N<1018) , 求有多少个经过 N 重组的数是 M(M≤100) 的倍数. 注意: ①重组不能有前导零; ②重组的数相同, 则只能算一个数. ...
- codeforces 401D. Roman and Numbers 数位dp
题目链接 给出一个<1e18的数, 求将他的各个位的数字交换后, 能整除m的数的个数. 用状态压缩记录哪个位置的数字已经被使用了, 具体看代码. #include<bits/stdc++. ...
- [Codefroces401D]Roman and Numbers(状压+数位DP)
题意:给定一个数,求将该数重新排列后mod m==0的方案数 重新排列就考虑到用到哪些数,以及此时mod m的值 于是dp[i][j]表示状态i中mod m==j的方案数 注意:转移的时候只要找到一种 ...
随机推荐
- BodeAbp前端介绍
BodeAbp的前端可以根据自己的喜好选型,推荐React.js.angular2.js.vue.js,后续我会以react.js为例说明BodeAbp前端的一些设计思路. BodeAbp提供的前端d ...
- JVM规范系列第4章:Class文件格式
这一章节讲的是字节码的整个组成格式,读懂了这一章,就读懂了字节码文件.对于这一章的学习,我更推荐作为工具书去查找.最好是找一个最简单的Hello World例子,一个字节一个字节去分析其含义.在分析过 ...
- 基于DDD的.NET开发框架ABP实例,多租户 (Saas)应用程序,采用.NET MVC, Angularjs, EntityFramework-介绍
介绍 基于ABPZERO的多租户 (Saas)应用程序,采用ASP.NET MVC, Angularjs-介绍 ASP.NET Boilerplate作为应用程序框架. ASP.NET MVC和ASP ...
- 基础-Math.floor与parseInt区别
Math.floor只能对一个数向下取整,不能解析字符串 如: Math.floor(1.5) // 1 Math.floor(-2.1) // -3 Math.floor("3" ...
- 第五届蓝桥杯C++B组 地宫取宝
代码: #include <bits/stdc++.h> using namespace std; #define ll long long const ll mod = 1e9 + 7; ...
- Linux下Vim使用备忘
1.Insert键,决定是Insert模式还是Replace模式. 2.Esc键,退出编辑模式(Insert Or Replace). 3.:wq (ZZ) 保存并退出Vim. http://caib ...
- MYSQL两个数据库字符集保持一致问题
参考这篇文章:https://lzw.me/a/mysql-charset.html 还有一篇官方文档:https://dev.mysql.com/doc/refman/5.7/en/charset. ...
- Linux CentOS虚拟机网卡配置
最近在VMware安装CentOS6.5之后,每次从宿主机访问虚拟机的Oracle时,都要修改IP地址,因为没有设置虚拟机的IP,所以每次开机之后虚拟机的IP地址都是随机的,于是研究了下给虚拟机配置静 ...
- python之tkinter使用-Grid(网格)布局管理器
# 使用tkinter编写登录窗口 # Grid(网格)布局管理器会将控件放置到一个二维的表格里,主控件被分割为一系列的行和列 # stricky设置对齐方式,参数N/S/W/E分别表示上.下.左.右 ...
- RSA,JAVA私钥加密,C#公钥解密
做这个东西在坑里爬了3天才爬出来,记录下供园友参考.C#程序员一枚,项目需要和Java做数据交互,对方甩了段密文和一个CER证书给我,然后我要对其密文进行解密. RSA 非对称加密,对方用私钥加密,我 ...