Codeforces Round #235 (Div. 2) D (dp)

以为是组合,后来看着像数位dp,又不知道怎么让它不重复用。。然后就没思路 了。

其实状压就可以了 状压是可以确定一个数的使用顺序的 利用01也可以确定所有的数的使用以及不重复

dp[i+1《《e][(j*10+p[e])%m]+=dp[i][j]; 排下序去掉重复的 或者最后除去每个数出现的次数

 1 #include <iostream>

 2 #include<cstdio>

 3 #include<cstring>

 4 #include<algorithm>

 5 #include<stdlib.h>

 6 #include<vector>

 7 #include<cmath>

 8 #include<queue>

 9 #include<set>

10 using namespace std;

11 #define N 100000

12 #define LL long long

13 #define INF 0xfffffff

14 const double eps = 1e-8;

15 const double pi = acos(-1.0);

16 const double inf = ~0u>>2;

17 LL dp[1<<18][100];

18 int o[20];

19 int main()

20 {

21     LL n;

22     int m,i,j,a;

23     while(cin>>n>>m)

24     {

25         memset(dp,0,sizeof(dp));

26         LL x = n;

27         int g = 0;

28         while(x)

29         {

30             o[g++] = x%10;

31             x/=10;

32         }

33         sort(o,o+g);

34         int pp= - 1;

35         for(i = 0 ; i < g ;i++)

36         if(o[i]!=pp&&o[i]!=0)

37         {

38             dp[1<<i][o[i]%m] = 1;

39             pp = o[i];

40         }

41         //dp[0][0] = 1;

42         //for(a = 2; a <= g ; a++)

43         //{

44             for(i = 0  ;i < (1<<g) ; i++)

45             {

46                 for(j = 0 ; j < m ;j++)

47                 {

48                     if(dp[i][j])

49                     {

50                         int pre = -1;

51                         for(int e = 0 ; e < g ;e++)

52                         {

53                             if(o[e]==pre) continue;

54                             if(i&(1<<e)) continue;

55                             if(i==0&&o[e]==0) continue;

56                             dp[i+(1<<e)][(j*10+o[e])%m]+=dp[i][j];

57                             pre = o[e];

58                         }

59                         

60                     }

61                 }

62             }

63        // }

64         cout<<dp[(1<<g)-1][0]<<endl;

65     }

66     return 0;

67 }
View Code

 

你可能感兴趣的:(codeforces)