题目链接:BZOJ 1072

这道题使用 C++ STL 的 next_permutation() 函数直接暴力就可以AC 。(使用 Set 判断是否重复)

代码如下:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <algorithm>
  6. #include <cmath>
  7. #include <set>
  8.  
  9. using namespace std;
  10.  
  11. int T, d, l, Ans;
  12. int A[15];
  13.  
  14. char Str[15];
  15.  
  16. typedef long long LL;
  17.  
  18. LL Num;
  19.  
  20. set<LL> S;
  21.  
  22. int main()
  23. {
  24. scanf("%d", &T);
  25. for (int Case = 1; Case <= T; Case++) {
  26. scanf("%s%d", Str, &d);
  27. Ans = 0;
  28. S.clear();
  29. l = strlen(Str);
  30. for (int i = 0; i < l; i++) A[i] = Str[i] - '0';
  31. sort(A, A + l);
  32. while (true) {
  33. Num = 0;
  34. for (int j = 0; j < l; j++) Num = Num * 10 + A[j];
  35. if (S.count(Num) == 0 && Num % d == 0) {
  36. ++Ans;
  37. S.insert(Num);
  38. }
  39. if (!next_permutation(A, A + l)) break;
  40. }
  41. printf("%d\n", Ans);
  42. }
  43. return 0;
  44. }

  

但是比较慢,正常一点的解法应该是使用状压 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])! (排列数)。

代码如下:

  1. #include <iostream>
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstring>
  5. #include <algorithm>
  6. #include <cmath>
  7.  
  8. using namespace std;
  9.  
  10. int T, d, l, Ans;
  11. int A[15], Cnt[15], f[1024 + 5][1000 + 5];
  12.  
  13. char Str[15];
  14.  
  15. int main()
  16. {
  17. scanf("%d", &T);
  18. for (int Case = 1; Case <= T; Case++) {
  19. scanf("%s%d", Str, &d);
  20. l = strlen(Str);
  21. memset(Cnt, 0, sizeof(Cnt));
  22. for (int i = 0; i < l; i++) {
  23. A[i] = Str[i] - '0';
  24. ++Cnt[A[i]];
  25. }
  26. memset(f, 0, sizeof(f));
  27. f[0][0] = 1;
  28. for (int i = 0; i < (1 << l); i++) {
  29. for (int j = 0; j < d; j++) {
  30. for (int k = 0; k < l; k++) {
  31. if ((i & (1 << k)) == 0)
  32. f[i | (1 << k)][(j * 10 + A[k]) % d] += f[i][j];
  33. }
  34. }
  35. }
  36. Ans = f[(1 << l) - 1][0];
  37. for (int i = 0; i <= 9; i++) {
  38. for (int j = 1; j <= Cnt[i]; j++) {
  39. Ans /= j;
  40. }
  41. }
  42. printf("%d\n", Ans);
  43. }
  44. return 0;
  45. }

  

[BZOJ 1072] [SCOI2007] 排列perm 【状压DP】的更多相关文章

  1. BZOJ 1072 [SCOI2007]排列perm ——状压DP

    [题目分析] 没什么好说的,水题. 代码比较丑,结果需要开long long 时间爆炸 [代码] #include <cstdio> #include <cstring> #i ...

  2. bzoj 1072: [SCOI2007]排列perm 状压dp

    code: #include <bits/stdc++.h> #define N 1005 using namespace std; void setIO(string s) { stri ...

  3. BZOJ 1072: [SCOI2007]排列perm 状态压缩DP

    1072: [SCOI2007]排列perm Description 给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0).例如123434有90种排列能被2整除,其中末位为 ...

  4. [BZOJ1072][SCOI2007]排列perm 状压dp

    1072: [SCOI2007]排列perm Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2488  Solved: 1546[Submit][St ...

  5. B1072 [SCOI2007]排列perm 状压dp

    很简单的状压dp,但是有一个事,就是...我数组开大了一点,然后每次memset就会T,然后开小就好了!!!震惊!以后小心点这个问题. 题干: Description 给一个数字串s和正整数d, 统计 ...

  6. BZOJ 1072 [SCOI2007]排列perm

    1072: [SCOI2007]排列perm Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1268  Solved: 782[Submit][Sta ...

  7. BZOJ 1072 [SCOI2007]安排perm 如压力DP

    意甲冠军:联系 方法:状压DP? 题解:这题事实上没啥好写的.不算非常难,推一推就能搞出来. 首先看到这个问题,对于被d整除这个条件,非常easy就想到是取余数为0,所以想到可能状态中刚開始含有取余数 ...

  8. 【以前的空间】bzoj 1072 [SCOI2007]排列perm

    又颓废了一个下午,最近撸mc撸到丧失意识了,玩的有点恶心,于是找水题做,瞧不起颓废的自己啊. another水题. 这题题意很明显啦,就是找数字排列后组成的数去mod d=0后有多少种. 普通的搜索的 ...

  9. 暑假集训Day 4 P4163 [SCOI2007]排列 (状压dp)

    状压dp (看到s的长度不超过10就很容易想到是状压dp了 但是这个题的状态转移方程比较特殊) 题目大意 给一个数字串 s 和正整数 d, 统计 s 有多少种不同的排列能被 d 整除(可以有前导 0) ...

随机推荐

  1. android 12 click事件的不同实现方式

    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layo ...

  2. Java序列化之Serializable

    Java的序列化流程如下: Java的反序列化流程如下: 注意:并不是所有类都需要进行序列化,主要原因有两个 1)安全问题.Java中有的类属于敏感类,此类的对象数据不便对外公开,而序列化的对象数据很 ...

  3. ubuntu环境配置之vi 配置【转载】

    ubuntu环境配置之vi 配置 [日期:2014-02-10] 来源:Linux社区  作者:zhonghe1114 [字体:大 中 小]   Android的源码开发,几乎离不开Linux,Lin ...

  4. 实践过配置成功的VNC安装配置

    VNC安装步骤说明那个 1.安装图形界面    #yum install tigervnc-server tigervnc  2.启动VNCServer #vncserver 对应的关闭图形界面的命令 ...

  5. Usaco 2010 Dec Gold Exercise(奶牛健美操)

    /*codevs 3279 二分+dfs贪心检验 堆版本 re一个 爆栈了*/ #include<cstdio> #include<queue> #include<cst ...

  6. PL/SQL 触发器简介

    与公司同事交流了一下,得知触发器很少用.性能是一方面,主要是如果用太多触发器,可能到时你都不知道会有什么操作自动发生. 有些操作可以在程序中控制.例如在插入某个表时,写个log表的记录.这可以用触发器 ...

  7. 国内流行的两大开源.net微信公众平台SDK对比分析

    最近忙于微信周边的开发 难免手痒去搜索一下有没有相关的sdk直接拿来使 还真发现了不少 这里总结两个看起来比较不错的.net平台下基于C#语言开发的SDK 一个强大一个小巧 (1) Senparc.W ...

  8. oracle 报Ora-01008错误:oracle 并非所有变量都已绑定的原因.TO_number();动态执行select..into..语句时

    1.sql_temp := 'UPDATE B38_back SET '||code||'=TO_NUMBER(nvl('||:NEW.BACAI||',0))+'||OnMonth || ' WHE ...

  9. oc常用正则表达式

    常用的第三方正则库: http://regexkit.sourceforge.net/RegexKitLite/index.html 匹配中文字符的正则表达式: [\u4e00-\u9fa5]评注:匹 ...

  10. EBS成本核算方法

    业务背景 成本核算方法,对应EBS系统中的成本方法,有四种: 1.标准成本 2.平均成本 平均成本又分为永续平均成本,即 Average Cost 期间平均成本,按照期间(自然月)来计算的平均成本 F ...