解题思路:根据dp规则,我们可以把d[i]值相同的放到一起,然后算一个总的DP就行了。

解题代码

Topcoder SRM655  DIV1 500 Nine_i++Topcoder SRM655  DIV1 500 Nine_#include_02
  1 // BEGIN CUT HERE
  2 /*
  3 
  4 */
  5 // END CUT HERE
  6 /*#line 7 "Nine.cpp"
  7 #include <cstdlib>
  8 #include <cctype>
  9 #include <cstring>
 10 #include <cstdio>
 11 #include <cmath>
 12 #include <algorithm>
 13 #include <vector>
 14 #include <string>
 15 #include <iostream>
 16 #include <sstream>
 17 #include <map>
 18 #include <set>
 19 #include <queue>
 20 #include <stack>
 21 #include <fstream>
 22 #include <numeric>
 23 #include <iomanip>
 24 #include <bitset>
 25 #include <list>
 26 #include <stdexcept>
 27 #include <functional>
 28 #include <utility>
 29 #include <ctime>
 30 using namespace std;
 31 
 32 #define PB push_back
 33 #define MP make_pair
 34 
 35 #define REP(i,n) for(i=0;i<(n);++i)
 36 #define FOR(i,l,h) for(i=(l);i<=(h);++i)
 37 #define FORD(i,h,l) for(i=(h);i>=(l);--i)
 38 #define M 1000000007
 39 
 40 typedef vector<int> VI;
 41 typedef vector<string> VS;
 42 typedef vector<double> VD;
 43 typedef long long LL;
 44 typedef pair<int,int> PII;
 45 
 46 const int maxn = 9*9*9*9*9;
 47 int dp2[5005][10];
 48 int pow9[6];
 49 int dp[maxn][32];
 50 void get_nx()
 51 {
 52     dp2[0][0] = 1 ;
 53     for(int i = 1;i<= 5000 ;i ++)
 54         for(int j = 0 ;j <= 9; j ++){
 55             for(int s = 0 ; s <= 9 ; s ++){
 56                 dp2[i][(j+s) % 9] =  (dp2[i][(j+s) %9] + dp2[i][j]) % M; 
 57             }
 58         }
 59 }
 60 class Nine
 61 {
 62         public:
 63         int count(int m, vector <int> d){
 64             memset(dp2,0,sizeof(dp2));
 65             get_nx();
 66             memset(dp,0,sizeof(dp));
 67             for()
 68             return dp[1][0];
 69         }
 70     public:
 71     void run_test(int Case) { if ((Case == -1) || (Case == 0)) test_case_0(); if ((Case == -1) || (Case == 1)) test_case_1(); if ((Case == -1) || (Case == 2)) test_case_2(); if ((Case == -1) || (Case == 3)) test_case_3(); if ((Case == -1) || (Case == 4)) test_case_4(); }
 72     private:
 73     template <typename T> string print_array(const vector<T> &V) { ostringstream os; os << "{ "; for (typename vector<T>::const_iterator iter = V.begin(); iter != V.end(); ++iter) os << '\"' << *iter << "\","; os << " }"; return os.str(); }
 74     void verify_case(int Case, const int &Expected, const int &Received) { cerr << "Test Case #" << Case << "..."; if (Expected == Received) cerr << "PASSED" << endl; else { cerr << "FAILED" << endl; cerr << "\tExpected: \"" << Expected << '\"' << endl; cerr << "\tReceived: \"" << Received << '\"' << endl; } }
 75     void test_case_0() { int Arg0 = 2; int Arr1[] = {1,2}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 4; verify_case(0, Arg2, count(Arg0, Arg1)); }
 76     void test_case_1() { int Arg0 = 2; int Arr1[] = {1,2,3}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 16; verify_case(1, Arg2, count(Arg0, Arg1)); }
 77     void test_case_2() { int Arg0 = 1; int Arr1[] = {0,0,1}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 200; verify_case(2, Arg2, count(Arg0, Arg1)); }
 78     void test_case_3() { int Arg0 = 5; int Arr1[] = {1,3,5,8,24,22,25,21,30,2,4,0,6,7,9,11,14,13,12,15,18,17,16,19,26,29,31,28,27,10,20,23}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 450877328; verify_case(3, Arg2, count(Arg0, Arg1)); }
 79     void test_case_4() { int Arg0 = 5; int Arr1[] = {31,31,31,31,31}; vector <int> Arg1(Arr1, Arr1 + (sizeof(Arr1) / sizeof(Arr1[0]))); int Arg2 = 11112; verify_case(4, Arg2, count(Arg0, Arg1)); }
 80 
 81 // END CUT HERE
 82 
 83 };
 84 
 85 // BEGIN CUT HERE
 86 int main()
 87 {
 88         Nine ___test;
 89         clock_t be,en;
 90         ___test.run_test(-1);
 91         return 0;
 92 }
 93 
 94 // END CUT HERE
 95 */
 96 
 97 #include <vector>
 98 #include <list>
 99 #include <map>
100 #include <set>
101 #include <deque>
102 #include <stack>
103 #include <bitset>
104 #include <algorithm>
105 #include <functional>
106 #include <numeric>
107 #include <utility>
108 #include <sstream>
109 #include <iostream>
110 #include <iomanip>
111 #include <cstdio>
112 #include <cmath>
113 #include <cstdlib>
114 #include <ctime>
115  
116 using namespace std;
117  
118 class Nine {
119 public:
120   int count(int, vector <int>);
121 };
122  
123 const int md = 1000000007;
124  
125 inline void add(int &a, int b) {
126   a += b;
127   if (a >= md) a -= md;
128 }
129  
130 inline int mul(int a, int b) {
131   return (long long)a * b % md;
132 }
133  
134 int f[33][100010];
135 int ways[5555][13];
136  
137 int Nine::count(int que, vector <int> d) {
138   int ds = d.size();
139   for (int i = 0; i <= ds; i++) {
140     for (int j = 0; j < 9; j++) {
141       ways[i][j] = 0;
142     }
143   }
144   ways[0][0] = 1;
145   for (int i = 0; i < ds; i++) {
146     for (int j = 0; j <= 9; j++) {
147       for (int k = 0; k <= 9; k++) {
148         int new_j = (j + k) % 9;
149         add(ways[i + 1][new_j], ways[i][j]);
150       }
151     }
152   }//预处理 多少位 余数为多少的情况数
153   int n = (1 << que);
154   vector <int> cnt(n, 0);
155   for (int i = 0; i < ds; i++) {
156     cnt[d[i]]++;
157   }
158   int MAX = 1;
159   for (int i = 0; i < que; i++) {
160     MAX *= 9;
161   }
162   for (int t = 0; t <= n; t++) {
163     for (int z = 0; z < MAX; z++) {
164       f[t][z] = 0;
165     }
166   }
167   f[0][0] = 1;
168   int cur[42];
169   for (int t = 0; t < n; t++) {
170     for (int z = 0; z < MAX; z++) {//max代表5个问题的情况压缩
171       int zz = z;
172       for (int i = 0; i < que; i++) {
173         cur[i] = zz % 9;
174         zz /= 9;
175       }//cur[i] 代表的是每一种状态的余数 
176 
177       for (int now = 0; now <= 9; now++) { //枚举位数
178 
179         int new_z = 0;
180         for (int i = que - 1; i >= 0; i--) {//que代表的是问题个数
181           new_z *= 9;
182           int digit = cur[i];
183           if (t & (1 << i)) {
184             digit += now;
185             if (digit >= 9) digit -= 9;
186           }
187           //
188           new_z += digit;
189         }
190         add(f[t + 1][new_z], mul(f[t][z], ways[cnt[t]][now]));//其实是一下加 cnt[t] 个值
191       }
192     }
193   }
194   return f[n][0];
195 }
196  
View Code