[BZOJ 1072] [SCOI2007] 排列perm 【状压DP】
题目链接:BZOJ 1072
这道题使用 C++ STL 的 next_permutation() 函数直接暴力就可以AC 。(使用 Set 判断是否重复)
代码如下:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <set> using namespace std; int T, d, l, Ans;
int A[15]; char Str[15]; typedef long long LL; LL Num; set<LL> S; int main()
{
scanf("%d", &T);
for (int Case = 1; Case <= T; Case++) {
scanf("%s%d", Str, &d);
Ans = 0;
S.clear();
l = strlen(Str);
for (int i = 0; i < l; i++) A[i] = Str[i] - '0';
sort(A, A + l);
while (true) {
Num = 0;
for (int j = 0; j < l; j++) Num = Num * 10 + A[j];
if (S.count(Num) == 0 && Num % d == 0) {
++Ans;
S.insert(Num);
}
if (!next_permutation(A, A + l)) break;
}
printf("%d\n", Ans);
}
return 0;
}
但是比较慢,正常一点的解法应该是使用状压 DP 。
设定一个状态 f[i][j] ,其中 i 的二进制表示当前已经使用了原数串中的某些位 (在 i 中为 1 的位) ,j 表示当前的数字 mod d 的值。f[i][j] 表示达到这个状态的方案数。
那么状态转移就是 : f[i | (1<<k)][(j * 10 + A[k]) % d] += f[i][j] ((i & (1<<k)) == 0)
由于原排列中的数字可能有重复的,所以我们计算了很多重复的方案数。
如果某个数字 i 在排列中出现了 Cnt[i] 次,那么最后的答案 Ans 应该 Ans /= (Cnt[i])! (排列数)。
代码如下:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath> using namespace std; int T, d, l, Ans;
int A[15], Cnt[15], f[1024 + 5][1000 + 5]; char Str[15]; int main()
{
scanf("%d", &T);
for (int Case = 1; Case <= T; Case++) {
scanf("%s%d", Str, &d);
l = strlen(Str);
memset(Cnt, 0, sizeof(Cnt));
for (int i = 0; i < l; i++) {
A[i] = Str[i] - '0';
++Cnt[A[i]];
}
memset(f, 0, sizeof(f));
f[0][0] = 1;
for (int i = 0; i < (1 << l); i++) {
for (int j = 0; j < d; j++) {
for (int k = 0; k < l; k++) {
if ((i & (1 << k)) == 0)
f[i | (1 << k)][(j * 10 + A[k]) % d] += f[i][j];
}
}
}
Ans = f[(1 << l) - 1][0];
for (int i = 0; i <= 9; i++) {
for (int j = 1; j <= Cnt[i]; j++) {
Ans /= j;
}
}
printf("%d\n", Ans);
}
return 0;
}
[BZOJ 1072] [SCOI2007] 排列perm 【状压DP】的更多相关文章
- BZOJ 1072 [SCOI2007]排列perm ——状压DP
[题目分析] 没什么好说的,水题. 代码比较丑,结果需要开long long 时间爆炸 [代码] #include <cstdio> #include <cstring> #i ...
- bzoj 1072: [SCOI2007]排列perm 状压dp
code: #include <bits/stdc++.h> #define N 1005 using namespace std; void setIO(string s) { stri ...
- BZOJ 1072: [SCOI2007]排列perm 状态压缩DP
1072: [SCOI2007]排列perm Description 给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0).例如123434有90种排列能被2整除,其中末位为 ...
- [BZOJ1072][SCOI2007]排列perm 状压dp
1072: [SCOI2007]排列perm Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 2488 Solved: 1546[Submit][St ...
- B1072 [SCOI2007]排列perm 状压dp
很简单的状压dp,但是有一个事,就是...我数组开大了一点,然后每次memset就会T,然后开小就好了!!!震惊!以后小心点这个问题. 题干: Description 给一个数字串s和正整数d, 统计 ...
- BZOJ 1072 [SCOI2007]排列perm
1072: [SCOI2007]排列perm Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1268 Solved: 782[Submit][Sta ...
- BZOJ 1072 [SCOI2007]安排perm 如压力DP
意甲冠军:联系 方法:状压DP? 题解:这题事实上没啥好写的.不算非常难,推一推就能搞出来. 首先看到这个问题,对于被d整除这个条件,非常easy就想到是取余数为0,所以想到可能状态中刚開始含有取余数 ...
- 【以前的空间】bzoj 1072 [SCOI2007]排列perm
又颓废了一个下午,最近撸mc撸到丧失意识了,玩的有点恶心,于是找水题做,瞧不起颓废的自己啊. another水题. 这题题意很明显啦,就是找数字排列后组成的数去mod d=0后有多少种. 普通的搜索的 ...
- 暑假集训Day 4 P4163 [SCOI2007]排列 (状压dp)
状压dp (看到s的长度不超过10就很容易想到是状压dp了 但是这个题的状态转移方程比较特殊) 题目大意 给一个数字串 s 和正整数 d, 统计 s 有多少种不同的排列能被 d 整除(可以有前导 0) ...
随机推荐
- 屏蔽全部统计代码(51.la cnzz 百度统计 谷歌分析师adsense、屏蔽淘宝客广告代码)的方法
支持百度统计 .51.la统计.cnzz统计.51yes统计.谷歌分析师.阿里妈妈淘宝客广告.chinaz弹窗.假设有很多其它的须要屏蔽的,欢迎联系 default7#zbphp.com 改动etc的 ...
- Light OJ 1114 Easily Readable 字典树
题目来源:Light OJ 1114 Easily Readable 题意:求一个句子有多少种组成方案 仅仅要满足每一个单词的首尾字符一样 中间顺序能够变化 思路:每一个单词除了首尾 中间的字符排序 ...
- XML解析技术研究(一)
摘要:XML作为过去十年中出现的最流行的技术之一,得到了广泛的应用,而其中XML解析技术是XML应用的关键.本文介绍了XML解析技术的研究动向,分析和比较了4种XML解析技术的优劣,并归纳总结了应 ...
- 【ES6】Set和Map中的NaN
在JavaScript中,有个有意思的的式子:NaN !== NaN.在Set中的元素的重复检查或者Map键的定位过程中,都是用的类似恒等的检查逻辑.该逻辑和恒等检查的主要区别就是:NaN等于自身.
- windows10UWP:如何判断一个文件或者文件夹是否存在?
使用 StorageFolder.TryGetItemAsync 方法,尝试按名称获取文件或文件夹,不需将错误捕捉逻辑添加到代码(就像使用 StorageFolder.GetItemAsync 一样) ...
- C#开发学习——内联表达式
<%@ 表示:引用 <%# 表示:绑定 <%= 表示:取值 <%= 变量名%> Response.Write()输出和<%=%>输出最后的效果是一样的 ...
- JS中escape 方法和C#中的对应
在项目中遇到js中escape过的json字符串,需要在C#中对应模拟编码,记得原来遇到过这个问题,但是当时没记录下来方案, 于是又搜索了一番,发现别人说的都是HttpUtility.UrlEncod ...
- ASP+MYSQL的配置及乱码解决
TempStr = "driver={MySQL ODBC 3.51 Driver};database="&strDB&";server="&a ...
- for循环,如何结束多层for循环
采用标签方式跳出,指定跳出位置, a:for(int i=0;i<n;i++) { b:for(int j=0;j<n;j++) { if(n=0) { break a; } } }
- java.lang.ClassCastException: java.math.BigDecimal cannot be cast to java.lang.String
http://blog.csdn.net/agileclipse/article/details/17161225 详情请点击链接查看