状压DP之排列perm
题目
[SCOI2007]排列
给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0)。例如123434有90种排列能被2整除,其中末位为2的有30种,末位为4的有60种。
输入格式
输入第一行是一个整数T,表示测试数据的个数,以下每行一组s和d,中间用空格隔开。s保证只包含数字0, 1, 2, 3, 4, 5, 6, 7, 8, 9.
输出格式
每个数据仅一行,表示能被d整除的排列的个数。
样例
样例输入
7
000 1
001 1
1234567890 1
123434 2
1234 7
12345 17
12345678 29
样例输出
1
3
3628800
90
3
6
1398
数据范围与提示
在前三个例子中,排列分别有1, 3, 3628800种,它们都是1的倍数。
100%的数据满足:s的长度不超过10, 1<=d<=1000, 1<=T<=15。
思路
- 这道题棘手的地方是如何将数转化为二进制数存储状态,所以,我们先不管他所在数位的具体数目是多少,用二进制记录状态(1代表有,0代表没有),就很明了了,再来考虑数的问题,开一个和原字符组长度相等的数组,记录相应数位的数大小,我们定义DP数组\(F[i][j]\)代表状态\(i\)下余数为\(j\)的排序个数,\(cnt[i]\)记录\(i\)出现次数(作用下文说明),用\(a[i]\)代表原字符串相应\(i-1\)位置上的数的大小;
- 接着我们在第一层枚举状态\(i\),第二层枚举余数\(k\),在此加判断,如果\(f[i][k]\)为0,不需要进行以下操作,为0叠加无效,第三层枚举在\(i\)状态后面插入的数字\(j\),如果\(j\)位的数字没有出现,则进行转移 \(f[(i|(1<<j))][(k*10+a[j+1])%mod] += f[i][k]\),上一状态的最优借叠加上来。
- 还有一点就是数字重复,这时候就体现\(cnt\)的作用了,记录某个数字出现的次数,这些数字相互交换位置答案一样,对于数字\(i\),出现\(cnt[i]\)次,那么有\(A^{cnt[i]}_{cnt[i]}\)重复,要用\(f[lim-1][0]\)除去,注意判零!!!(还有一种去重方法,详细见<刘某>)
上代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=1<<11,maxm=1000+10;
int f[maxn][maxm];//f[i][j]表示状态i余数为j的排序个数
int T,mod;
int a[maxn],cnt[maxn];//cnt记录某个数i出现的次数
char s[15];
int J[]={0,1,2,6,24,120,720,5040,40320,362880,3628800};
int main(){
scanf("%d",&T);
while(T--){
memset(cnt, 0, sizeof(cnt));//一定记得初始化
memset(f, 0, sizeof(f));
scanf("%s%d",s,&mod);
int len=strlen(s);
for(int i=0;i<len;i++){
a[i+1]=s[i]-'0';
cnt[a[i+1]]++;//记录a[i+1]出现次数
}
int lim=1<<len;//记录界限
f[0][0]=1;//初始化临界状态,0状态下余数为0的有1种情况
for(int i=0;i<lim;i++){//枚举状态
for(int k=0;k<mod;k++){//枚举余数
if(f[i][k]){//假如没有跳过
for(int j=0; j<len; j++)//枚举插入的数字
if( (i & (1<<j)) == 0 )//无交集
f[(i|(1<<j))][(k*10+a[j+1])%mod] += f[i][k];//叠加
}
}
}
int ans=f[lim-1][0];
for(int i=0; i<=9; i++) if( cnt[i] ) ans /= J[cnt[i]];//去重
cout<<ans<<endl;
}
}
状压DP之排列perm的更多相关文章
- [BZOJ 1072] [SCOI2007] 排列perm 【状压DP】
题目链接:BZOJ 1072 这道题使用 C++ STL 的 next_permutation() 函数直接暴力就可以AC .(使用 Set 判断是否重复) 代码如下: #include <io ...
- BZOJ1072 排列perm 【状压dp】
Description 给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0).例如123434有90种排列能 被2整除,其中末位为2的有30种,末位为4的有60种. Inpu ...
- B1072 [SCOI2007]排列perm 状压dp
很简单的状压dp,但是有一个事,就是...我数组开大了一点,然后每次memset就会T,然后开小就好了!!!震惊!以后小心点这个问题. 题干: Description 给一个数字串s和正整数d, 统计 ...
- 排列perm HYSBZ - 1072(状压dp/暴力)
Description 给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0).例如123434有90种排列能被2整除,其中末位为2的有30种,末位为4的有60种. Input ...
- 「状压DP」「暴力搜索」排列perm
「状压DP」「暴力搜索」排列 题目描述: 题目描述 给一个数字串 s 和正整数 d, 统计 sss 有多少种不同的排列能被 d 整除(可以有前导 0).例如 123434 有 90 种排列能被 2 整 ...
- 【BZOJ1072】【SCOI2007】排列 [状压DP]
排列 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 给一个数字串s和正整数d, 统计s有多 ...
- 暑假集训Day 4 P4163 [SCOI2007]排列 (状压dp)
状压dp (看到s的长度不超过10就很容易想到是状压dp了 但是这个题的状态转移方程比较特殊) 题目大意 给一个数字串 s 和正整数 d, 统计 s 有多少种不同的排列能被 d 整除(可以有前导 0) ...
- K - Painful Bases 状压dp
Painful Bases LightOJ - 1021 这个题目一开始看,感觉有点像数位dp,但是因为是最多有16进制,因为限制了每一个数字都不同最多就有16个数. 所以可以用状压dp,看网上题解是 ...
- HDU5816 Hearthstone(状压DP)
题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=5816 Description Hearthstone is an online collec ...
随机推荐
- 浅谈js原型
前言 突发奇想,想写一篇原型的文章,也可能是因为对原型有更深的理解吧,在这里做个记录,来记录下自己的理解加深下记忆. 总之,希望本文的内容能够对您的学习或者工作有所帮助.另,如果有任何的错误或者不足请 ...
- 一个Redis查询案例
1.远程登陆进服务器 使用ssh连接至Linux服务器中 2.接入redis集群 redis-cli -h 10.1.8.12 -p 29000 3.执行查询命令 根据userid查询用户的最近在线时 ...
- Azure AD(四)知识补充-服务主体
一,引言 又到了新的一周了,也到了我新的分享的时间了,还记得上一周立得Flag,其中 “保证每周输出一篇文章” ,让我特别“在意”(这里用词不太恰当).主要是我的一个大学舍友,他突然问了我一个关于写博 ...
- Redis的内存和实现机制
1. Reids内存的划分 数据 内存统计在used_memory中 进程本身运行需要内存 Redis主进程本身运行需要的内存占用,代码.常量池等 缓冲内存,客户端缓冲区.复制积压缓冲区.AOF缓冲区 ...
- EIGRP-12-弥散更新算法-DUAL的FSM(*没写完)
FD (可行距离).后继和可行后继.本地计算和弥散计算(随着查询包的发出而扩散,随着响应包的接收而收敛)一到目前为止介绍的这些机制能够使路由器有效地计算出去往某目地的新路径,只要在整个弥散计算中不再出 ...
- Excel常用公式大全
公式是单个或多个函数的结合运用. AND “与”运算,返回逻辑值,仅当有参数的结果均为逻辑“真(TRUE)”时返回逻辑“真(TRUE)”,反之返回逻辑“假(FALSE)”. 条件判断 AVERAGE ...
- 8种排序算法 Java实现
冒泡排序 O(n2) 两个数比较大小,较大的数下沉,较小的数冒起来. public static void bubbleSort(int[] a) { //临时变量 int temp; //i是循环次 ...
- selenium(3)-针对鼠标的操作
背景 用selenium做自动化,有时候会遇到需要模拟鼠标操作才能进行的情况,比如单击.双击.点击鼠标右键.拖拽等等. 而selenium给我们提供了一个类来处理这类事件-----------Acti ...
- Java多线程之volatile详解
本文目录 从多线程交替打印A和B开始 Java 内存模型中的可见性.原子性和有序性 Volatile原理 volatile的特性 volatile happens-before规则 volatile ...
- 如何用 React 构建前端架构
早期的前端是由后端开发的,最开始的时候仅仅做展示,点一下链接跳转到另外一个页面去,渲染表单,再用Ajax的方式请求网络和后端交互,数据返回来还需要把数据渲染到DOM上.写这样的代码的确是很简单.在We ...