Description

  给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0)。例如123434有90种排列能
被2整除,其中末位为2的有30种,末位为4的有60种。

Input

  输入第一行是一个整数T,表示测试数据的个数,以下每行一组s和d,中间用空格隔开。s保证只包含数字0, 1
, 2, 3, 4, 5, 6, 7, 8, 9.

Output

  每个数据仅一行,表示能被d整除的排列的个数。

Sample Input

7
000 1
001 1
1234567890 1
123434 2
1234 7
12345 17
12345678 29

Sample Output

1
3
3628800
90
3
6
1398

HINT

在前三个例子中,排列分别有1, 3, 3628800种,它们都是1的倍数。

【限制】

100%的数据满足:s的长度不超过10, 1<=d<=1000, 1<=T<=15

 
 

题解

暴力可以过,但状压dp才是正解。
 
设f[s][j]表示状态s下【s表示已经选择了哪些数】余数为j的方案数,那么f[s | (1<<i-1)][(j * 10 + a[i])%d] += f[s][j]
很明显,状态s下可以通过在末尾添加一个不在状态中的i号数来转移到s|(1<<i-1)这个状态
 
设立一个状态(突然不知道怎么用语言描述这个状态)DP(I,J),IDP(I,J),I表示当前枚举的状态,JJ表示状态I对应的数字的数值,这样设立状态后很容易得出下面的状态转移方程: 
 

其中判断语句的含义是在II状态中,KK号没有选择出来。

状态转移结束后,由于数串中可能存在重复的数字(样例已经给出来了),这个时候我们就会有许多重复的计算。这个问题很好解决,我们根据排列的知识将最后的Ans/=Cnt[I] Cnt[I] 记录数字I在数串中出现的次数)就可以了。

C++代码/暴力

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int a[],b[];
  4. int n ,d;
  5. int ans ;
  6. void dfs(int i,long long x){
  7. if(i > n){
  8.  
  9. if(x % d == ) ans ++;
  10. return;
  11. }
  12. for(int j = ;j <= ;j ++){
  13. if(b[j]) {
  14. --b[j];
  15. dfs(i + ,x * + j);
  16. ++b[j];
  17. }
  18. }
  19. }
  20.  
  21. int main(){
  22. int t;
  23. cin >> t;
  24. while(t--){
  25. string str;
  26. cin >> str;
  27. ans = ;
  28. n = str.size();
  29. memset(a,,sizeof a);
  30. memset(b,,sizeof b);
  31. for(int i = ; i < str.size() ; i++){
  32. a[i] = str[i] - '';
  33. b[a[i]]++;
  34. }
  35. cin >> d;
  36. dfs(,);
  37. cout << ans << endl;
  38. }
  39. }

C++代码/状压

  1. #include <cmath>
  2. #include <cstdio>
  3. #include <cstring>
  4. #include <iostream>
  5. #include <algorithm>
  6. #define DB double
  7. #define SG string
  8. #define LL long long
  9. #define DP(A,B) DP[A][B]
  10. #define Fp(A,B,C,D) for(A=B;A<=C;A+=D)
  11. #define Fm(A,B,C,D) for(A=B;A>=C;A-=D)
  12. #define Clear(A) memset(A,0,sizeof(A))
  13. using namespace std;
  14. const LL Mod=1e9+;
  15. const LL Max=2e3+;
  16. const LL Inf=1e18;
  17. LL T,M,Num[Max],Cnt[Max],DP[Max][Max];
  18. inline LL Read(){
  19. LL X=;char CH=getchar();bool F=;
  20. while(CH>''||CH<''){if(CH=='-')F=;CH=getchar();}
  21. while(CH>=''&&CH<=''){X=(X<<)+(X<<)+CH-'';CH=getchar();}
  22. return F?-X:X;
  23. }
  24. inline void Write(LL X){
  25. if(X<)X=-X,putchar('-');
  26. if(X>)Write(X/);
  27. putchar(X%+);
  28. }
  29. int main(){
  30. LL I,J,K,L;
  31. T=Read();
  32. while(T--){
  33. Clear(Cnt);Clear(DP);
  34. char CH[];scanf("%s",CH+);
  35. LL Length=strlen(CH+);M=Read();
  36. Fp(I,,Length,){
  37. Num[I]=CH[I]-'';
  38. Cnt[Num[I]]++;
  39. }DP(,)=;
  40. K=(<<Length)-;
  41. Fp(I,,K,){
  42. Fp(J,,M-,){
  43. Fp(L,,Length,){
  44. if((I&(<<(L-)))==){
  45. DP(I|(<<(L-)),((J<<)+(J<<)+Num[L])%M)+=DP(I,J);
  46. }
  47. }
  48. }
  49. }LL Ans=DP(K,);
  50. Fp(I,,,){
  51. Fp(J,,Cnt[I],){
  52. Ans/=J;
  53. }
  54. }Write(Ans);putchar('\n');
  55. }
  56. return ;
  57. }

排列perm HYSBZ - 1072(状压dp/暴力)的更多相关文章

  1. N - 寿司晚宴 HYSBZ - 4197 状压dp

    N - 寿司晚宴 HYSBZ - 4197 推荐题解 这个题目我觉得还是很难的,借助题解写出来的,题解还看了很久,现在还是不是很理解. 首先这个数比较大有500,如果直接就像这个题目S - Query ...

  2. bzoj 1072状压DP

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

  3. bzoj 1072 状压DP

    我们用w[i][j]来表示,i是一个二进制表示我们选取了s中的某些位,j表示这些位%d为j,w[i][j]则表示这样情况下的方案数,那么我们可以得到转移.w[i|(1<<k)][(j*10 ...

  4. K - Painful Bases 状压dp

    Painful Bases LightOJ - 1021 这个题目一开始看,感觉有点像数位dp,但是因为是最多有16进制,因为限制了每一个数字都不同最多就有16个数. 所以可以用状压dp,看网上题解是 ...

  5. [BZOJ 1072] [SCOI2007] 排列perm 【状压DP】

    题目链接:BZOJ 1072 这道题使用 C++ STL 的 next_permutation() 函数直接暴力就可以AC .(使用 Set 判断是否重复) 代码如下: #include <io ...

  6. 「状压DP」「暴力搜索」排列perm

    「状压DP」「暴力搜索」排列 题目描述: 题目描述 给一个数字串 s 和正整数 d, 统计 sss 有多少种不同的排列能被 d 整除(可以有前导 0).例如 123434 有 90 种排列能被 2 整 ...

  7. BZOJ1072 排列perm 【状压dp】

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

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

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

  9. CCF 201312-4 有趣的数 (数位DP, 状压DP, 组合数学+暴力枚举, 推公式, 矩阵快速幂)

    问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次. 2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前. 3. 最高 ...

随机推荐

  1. js 反斜杠 处理

    var t = jsonstr.replace(/\\/g,"\\\\\\\\"); --\\ 表示 代码 输出 \' 单引号 \" 双引号 \& 和号 \\ 反 ...

  2. 一些 sql 调优的总结

    一.sql 优化方案 1)列类型尽量定义成数值类型,且长度尽可能短,如主键和外键,类型字段等等   2)建立单列索引   3)根据需要建立多列联合索引.当单个列过滤之后还有很多数据,那么索引的效率将会 ...

  3. 网络相关辅助类NetUtils

    package yqw.java.util; import java.net.NetworkInterface;import java.util.ArrayList;import java.util. ...

  4. ModelSerializer 使用知识点_serializers.SerializerMethodField()使用场景总结

    serializers.SerializerMethodField和钩子方法结合,可以实现对ModelSerializer类的一些字段进行二次加工,返回,如下:1.对以ModelSerializer的 ...

  5. 【转】毛虫算法——尺取法

    转自http://www.myexception.cn/program/1839999.html 妹子满分~~~~ 毛毛虫算法--尺取法 有这么一类问题,需要在给的一组数据中找到不大于某一个上限的&q ...

  6. @清晰掉 qsort()

    qsort函数描述: http://www.cnblogs.com/sooner/archive/2012/04/18/2455011.html qsort()函数实现: /*** *qsort.c ...

  7. STOMP协议详解

      STOMP协议详解 作者:chszs,转载需注明.博客主页:http://blog.csdn.net/chszs 一.STOMP协议介绍 STOMP即Simple (or Streaming) T ...

  8. 将项目发布到neuxs私服

    需要在 pom.xml中配置 <distributionManagement> <repository> <id>user-release</id> & ...

  9. bash中的set, env, export unset的区别

    参考这篇文章很好 参考这篇文章2 -------------------------- == set显示的是当前shell的变量, 不同的shell, 它的私有变量是不同的 env是显示用户的变量, ...

  10. 纯css闪烁效果

    .i-i-box-active{ -webkit-animation: shan666 1s infinite ease-in-out; animation: shan666 1s infinite ...