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
原文地址:https://www.cnblogs.com/shangyu/p/3594914.html