题解-Roman and Numbers
题解-Roman and Numbers
前置知识:
数位 \(\texttt{dp}\) </>
给定 \(n\) 和 \(m\),求将 \(n\) 的各位数字重新排列(不允许有前导 \(0\)),求可以构造几个能被 \(m\) 整除。
数据范围:\(1\le n\le 10^{18}\),\(1\le m\le 100\)。
用数位 \(\texttt{dp}\) 代码又短时间又优又好理解,为什么没人玩呢?
把 \(n\) 的各位数字拿出来排序一下,然后把每个数有没有用过状压。
for(;n;n/=10) d.pb(n%10);
sort(d.begin(),d.end()),len=d.size();
选数字的时候只允许用相同数字中第一个没用过的。
\(\texttt{Dfs}\) 中:
- \(w\):要找从右往左第几位。
- \(st\):当前数字使用状态。
- \(sum\):左 \(len-w\) 位数字形成的数 \(\bmod m\) 的余数。
il lng Dfs(re int w,re int st,re int sum){
if(!w) return sum==0;//判断被 m 整除
if(~f[st][sum]) return f[st][sum];
re lng res=0;
for(re int i=0;i<len;i++)
if(!((1<<i)&st)&&(i==0||d[i]!=d[i-1]||((1<<(i-1))&st))) //*
res+=Dfs(w-1,st|(1<<i),(sum*10+d[i])%m);
return f[st][sum]=res; //记忆化,记录答案
}
其中 \(*\) 处的判断:
- 该数字未用过。
- 该数字前的相同数字都用过。
以保证使用顺序,防止重复统计。
关于 \(f\) 记忆化数组:
现在是 \(f_{st,sum}\),本来应该是 \(f_{w,st,sum}\)。这里就讲讲 \(f_{w,st,sum}\) 记忆化的缺点:
- \(1\le w\le 18\),\(1\le st\le 2^{18}\),\(1\le sum<m\le 100\),必然 \(\color{#117}{\texttt{MLE}}\)。
- \(st\) 中 \(1\) 的数量 \(cnt\) 必然满足 \(cnt=len-w\),所以只记录 \(st\) 不会重合答案。
时间复杂度 \(\Theta(2^{len}m)\)。
Code
#include <bits/stdc++.h>
using namespace std;
//&Start
#define re register
#define il inline
#define mk make_pair
#define pb push_back
#define db double
#define lng long long
#define fi first
#define se second
#define inf 0x3f3f3f3f
//&Data
const int W=18,M=100;
int m,len;
lng n,f[1<<W|7][M|7];
vector<int> d;
//&Digitdp
il void Pre(){memset(f,-1,sizeof f);}
il lng Dfs(re int w,re int st,re int sum){
if(!w) return sum==0;
if(~f[st][sum]) return f[st][sum];
re lng res=0;
for(re int i=0;i<len;i++)
if(!((1<<i)&st)&&(i==0||d[i]!=d[i-1]||((1<<(i-1))&st)))
res+=Dfs(w-1,st|(1<<i),(sum*10+d[i])%m);
return f[st][sum]=res;
}
il lng DP(){
for(;n;n/=10) d.pb(n%10);
sort(d.begin(),d.end()),len=d.size();
re lng res=0;
for(re int i=0;i<len;i++)
if(d[i]&&(i==0||d[i]!=d[i-1])) // 这里也要判断!这是最容易错的地方
res+=Dfs(len-1,1<<i,d[i]%m);
return res;
}
//&Main
int main(){
scanf("%lld%d",&n,&m),Pre();
printf("%lld\n",DP());
return 0;
}
祝大家学习愉快!
题解-Roman and Numbers的更多相关文章
- 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 ...
- 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 ...
- [LeetCode 题解]: Add Two Numbers
You are given two linked lists representing two non-negative numbers. The digits are stored in rever ...
- [LeetCode 题解]: Roman to Interger
前言 [LeetCode 题解]系列传送门: http://www.cnblogs.com/double-win/category/573499.html 1.题目描述 Given a ro ...
- CF401D Roman and Numbers 状压DP
CF401D 题意翻译 将n(n<=10^18)的各位数字重新排列(不允许有前导零) 求 可以构造几个mod m等于0的数字 题目描述 Roman is a young mathematicia ...
- leetcode 题解 Add Two Numbers(两个单链表求和)
题目: You are given two linked lists representing two non-negative numbers. The digits are stored in r ...
- Codeforces 401D Roman and Numbers
题目大意 Description 给定一个数 N(N<1018) , 求有多少个经过 N 重组的数是 M(M≤100) 的倍数. 注意: ①重组不能有前导零; ②重组的数相同, 则只能算一个数. ...
- LeetCode题解——Roman to Integer
题目: 将罗马数字转换为整数. 解法: 可以参考上一篇数字转换为罗马数字的规则. 代码: class Solution { public: int sym2int(char sym) //罗马数字字符 ...
随机推荐
- 七:Redis的持久化
1.RDB(Redis DataBase) 1.1 定义:在指定的时间间隔内将内存中的数据集快照写入磁盘,也就是行话讲的snapshot快照,他恢复时是将快照文件直接读到内存里 是什么:Redis会单 ...
- 动态导航栏和JavaScript箭头函数
动态导航栏和JavaScript箭头函数 今天我们来写一下动态的导航栏,并且学一下JavaScript的箭头函数等相关问题. 样式如下所示: html中执行代码如下所示: <!DOCTYPE h ...
- 2020-11-02(三年之约D92)-优秀不是一种行为,而是一种习惯
1.阅读:<软技能-代码之外的生存指南>- 第45章 培养习惯:刷新你的代码 成就我们的恰恰就是那些不断重复做的事情.因此,优秀不是一种行为,而是一种习惯--亚里士多德 习惯主要由三个要素 ...
- elasticsearch集群安装+安全验证+kibana安装
准备环境 启动4个centos容器, 并暴露相对应端口 (我的本机ip为172.16.1.236,以下涉及到的地方需要修改为自己的ip) node_name ip http port transpor ...
- Matlab项目经验分享-去除震荡点
Matlab是做科研是比较常用的建模工具,我在研一做项目期间遇到了一个还算比较基础的问题,所以我打算记录下来并分享出来! 处理问题步骤: 1. 抛出问题 2. 思考解决方法 3. 代码验证看结果 抛出 ...
- Shodan搜索引擎详解及Python命令行调用
shodan常用信息搜索命令 shodan配置命令 shodan init T1N3uP0Lyeq5w0wxxxxxxxxxxxxxxx //API设置 shodan信息收集 shodan myip ...
- 推荐一款比迅雷下载速度快的mac下载器
Folx和迅雷是2款支持在Mac系统上进行文件资源下载的工具,两者都支持BT种子资源的下载和直链下载,但Folx还另外支持了下载计划的自定义和智能限速功能.本文主要是为了比较Folx和迅雷在下载同一资 ...
- 思维导图软件iMindMap怎么用模板制作思维导图
随着思维导图的不断发展,市场上相关的软件也越来越多.像XMind.MindManager等.每一款软件都有它独特的亮点.作为众多思维导图软件中的一款,iMindMap算是比较亮眼的了.现在很多人都在用 ...
- Elasticsearch搜索资料汇总
Elasticsearch 简介 Elasticsearch(ES)是一个基于Lucene 构建的开源分布式搜索分析引擎,可以近实时的索引.检索数据.具备高可靠.易使用.社区活跃等特点,在全文检索.日 ...
- jquery删除文件
1 <div class="panel panel-default"> 2 <div class="panel-body"> 3 < ...