暑假集训Day 4 P4163 [SCOI2007]排列 (状压dp)
状压dp
(看到s的长度不超过10就很容易想到是状压dp了
但是这个题的状态转移方程比较特殊)
题目大意
给一个数字串 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
算法分析
- 这个题的思路还是蛮偏的,,,,但是很好理解
我们将f数组的第一维定义为状态 (最大值为1<<10) 第二维定义为 余数
那么问题就来了 如果我们把第一维定义为状态的话 应该是怎样的状态呢?
还是一样举个栗子:
给出的数为1234 我们就定义一个1<<4大小的状态 然后每一位表示对应该位置的数是否已经添加
比如0101就表示此时我们已经添加了2和4还有1和3没有添加进去 下一次可以选择添加进去1或者3 - 循环顺序
第一层循环状态 第二层循环余数 第三层循环下一个添加的数字
则转移方程就是f[i|1<<k][(j * 10+k)%d] += f[i][j]
第一维是i|1<<k 显然就是加上k位置的数字
第二维是(j * 10+k)%d 即上一位的余数再加上当前位 然后整个再%d
*转移条件
如果当前状态向下个状态转移的时候 即加上第k位置数字 这个已经转移过了 那么显然就不能再加一次了
判断语句就是
if((i & (1<<k)) == 0)
此时状态为i 想要转移的状态为i|1<<k 如果i&1<<k != 0 即表示i在第k位为1 也就是表示这个状态已经转移过了 所以要保证==0的时候再转移
- 需要注意有的数字是重复的 显然根据排列组合的规律 除以这个重复数字的全排列即可 即除以该数的阶乘(可以预处理或者写个函数 这里提供函数的代码)
代码展示
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
int f[1<<10][1001],T,a[maxn],d,cnt[11];
char s[maxn];
int jc(int x){
int u = 1;
for(int i = 1;i <= x;++i)u *= i;
return u;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%s%d",s,&d);
int len = strlen(s);
memset(cnt,0,sizeof(cnt));
memset(f,0,sizeof(f));
for(int i = 0;i < len;++i){
a[i] = s[i] - '0';
cnt[a[i]]++;
}
int maxs = (1<<len)-1;
f[0][0] = 1;
for(int i = 0;i <= maxs;++i){
for(int j = 0;j < d;++j)
if(f[i][j])
for(int k = 0;k < len;++k)
if((i & (1<<k)) == 0)
f[i|(1<<k)][(j*10+a[k])%d] += f[i][j];
}
int ans = f[maxs][0];
for(int i = 0;i <= 9;++i){
if(cnt[i]!=0)ans/=jc(cnt[i]);
}
printf("%d\n",ans);
}
return 0;
}
谢谢观看
点个关注>)<
暑假集训Day 4 P4163 [SCOI2007]排列 (状压dp)的更多相关文章
- 【BZOJ1072】【SCOI2007】排列 [状压DP]
排列 Time Limit: 10 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 给一个数字串s和正整数d, 统计s有多 ...
- LOJ #6037.「雅礼集训 2017 Day4」猜数列 状压dp
这个题的搜索可以打到48分…… #include <cstdio> #include <cstring> #include <algorithm> ; bool m ...
- P4163 [SCOI2007]排列——next_permutation
P4163 [SCOI2007]排列 注意要排序: next_permutation prev_permutation #include<cstdio> #include<cstri ...
- 暑假集训Day2 互不侵犯(状压dp)
这又是个状压dp (大型自闭现场) 题目大意: 在N*N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. ...
- [BZOJ 1072] [SCOI2007] 排列perm 【状压DP】
题目链接:BZOJ 1072 这道题使用 C++ STL 的 next_permutation() 函数直接暴力就可以AC .(使用 Set 判断是否重复) 代码如下: #include <io ...
- B1072 [SCOI2007]排列perm 状压dp
很简单的状压dp,但是有一个事,就是...我数组开大了一点,然后每次memset就会T,然后开小就好了!!!震惊!以后小心点这个问题. 题干: Description 给一个数字串s和正整数d, 统计 ...
- LUOGU P4163 [SCOI2007]排列
传送门 解题思路 首先我们发现这道题s的长度很小,所以考虑点暴力的做法,状压dp或搜索.本蒟蒻搜索永远调不对,所以就写了个状压dp.因为所有s里的数都要出现一次,并且最后的答案是要求整除,那么我们设d ...
- 暑假集训 || 状压DP
emm 位操作实现技巧: 获得第i位的数据: if(!(data & (1<< i))) 则data的第 i 位为0,else 为 1 设置第i位为1,data=(data | ...
- 暑假集训Day2 状压dp 特殊方格棋盘
首先声明 : 这是个很easy的题 可这和我会做有什么关系 题目大意: 在n*n的方格棋盘上放置n个车,某些格子不能放,求使它们不能互相攻击的方案总数. 注意:同一行或同一列只能有一个车,否则会相互攻 ...
随机推荐
- jchdl - GSL实例 - Shifter
https://mp.weixin.qq.com/s/ngQji-xi4FCCbL_2ihUi_A Shifter是移位节点的父类,定义了输入输出线,但是没有定义具体的移位方式,这个留给子类去实现 ...
- Rocket - decode - 几个问题
https://mp.weixin.qq.com/s/pMsK_E4mQrm3QXdnp7nDPQ 讨论指令解码部分遗留的几个问题. 1. 最小项与蕴含项之间的关系 参考链接: htt ...
- Linux (七)权限控制
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 1. 概述 Linux需要对登录用户读写执行文件.进入目录.查看增删目录内容等操作进行控制,不能任由用户 ...
- Java实现 蓝桥杯VIP 算法训练 JAM计数法
题目描述 Jam是个喜欢标新立异的科学怪人.他不使用阿拉伯数字计数,而是使用小 写英文字母计数,他觉得这样做,会使世界更加丰富多彩.在他的计数法中,每个数字的位数都是相同的(使用相同个数的字母),英文 ...
- Java实现 蓝桥杯 算法训练 寻找数组中最大值
算法训练 寻找数组中最大值 时间限制:1.0s 内存限制:512.0MB 提交此题 问题描述 对于给定整数数组a[],寻找其中最大值,并返回下标. 输入格式 整数数组a[],数组元素个数小于1等于10 ...
- Java实现 蓝桥杯 算法提高 三角形
算法提高 12-1三角形 时间限制:1.0s 内存限制:256.0MB 提交此题 问题描述 为二维空间中的点设计一个结构体,在此基础上为三角形设计一个结构体.分别设计独立的函数计算三角形的周长.面积. ...
- java实现三角螺旋阵
方阵的主对角线之上称为"上三角". 请你设计一个用于填充n阶方阵的上三角区域的程序.填充的规则是:使用1,2,3-.的自然数列,从左上角开始,按照顺时针方向螺旋填充. 例如:当n= ...
- Java实现第九届蓝桥杯耐摔指数
耐摔指数 题目描述 x星球的居民脾气不太好,但好在他们生气的时候唯一的异常举动是:摔手机. 各大厂商也就纷纷推出各种耐摔型手机.x星球的质监局规定了手机必须经过耐摔测试,并且评定出一个耐摔指数来,之后 ...
- JNI_day02
二级指针 指向指针变量的指针,保存指针的地址 结构体 struct Student //struct Stdent 学生结构体类型 { int id;//成员 char name[20]; int a ...
- 95题--不同的二叉搜索树II(java、中等难度)
题目描述:给定一个整数 n,生成所有由 1 ... n 为节点所组成的 二叉搜索树 . 示例如下: 分析:这一题需要对比LeetCode96题来分析:https://www.cnblogs.com/K ...