Topcoder SRM655 DIV1 500 Nine

题意:这题是http://www.cnblogs.com/zyue/p/4436075.html 这题的加强版。

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

解题代码

  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  

时间: 2024-10-04 10:12:15

Topcoder SRM655 DIV1 500 Nine的相关文章

TopCoder SRM502 Div1 500 贪心 01背包

原文链接https://www.cnblogs.com/zhouzhendong/p/SRM502-500.html SRM502 Div1 500 好题. 首先,如果已经确定了解决所有问题的优先级,只需要对于每一个问题是否被解决做出决策,那么显然直接 01 背包就好了. 事实上,我们是可以贪心地确定两个问题的优先程度的. 对于两个问题,假设分别为 a 和 b,则先做 a 再紧接着做 b 和先做 b 再紧接着做 a 的收益之差为 \[ \begin{eqnarray*} &&(-dec_a

SRM 618 DIV1 500

非常棒的组合问题,看了好一会,无想法.... 有很多做法,我发现不考虑顺序的最好理解,也最好写. 结果一定是两种形式 A....A   dp[n-1] A...A...A sgma(dp[j]*dp[n-j-1])( 1<=j<=n-2) 最后乘上n! 什么时候才能自己在比赛中做出一个500分来啊!!! class LongWordsDiv1 { public : int count(int n) { int i,j; fact[0] = 1; for(i = 1; i <= n; i

Topcoder SRM 630 (500 floyed 暴力 _builtin_popcount())

题意:给n个点,保证图联通,给点相连的距离,求一个最多的点,这些点之间的距离都是相同的. 分析: 下面的代码是我们房间第一的大神的,写的很简洁,我的思路和他的一样,但是我不知道错哪了. 思路是暴力枚举,最多有10个点,先用floyed计算出每两点之间的距离,然后用位运算暴力枚举, 枚举每个点是否加入进去,并用set把每个加入进去的点之间的距离加进去,如果距离唯一,说明点之间所有的距离相同, 然后用_builtin_popcount()计算二进制中多少个1 ,即表示加入了多少个点,求最大. Top

topcoder SRM628 div2 500(转)

Problem Statement      We have three types of brackets: "()", "[]", and "{}". We are now interested in some special strings. A string is special if all the following conditions hold: Each character of the string is one of the

Topcoder SRM 655 DIV1 500 FoldingPaper2 递归 + 枚举

题意:给你一张长W,宽H 的纸,问你能不能者成给定的大小, 每一次折纸只能折成整数大小. 解题思路:递推+枚举   枚举给定大小的长和宽,然后套进 W,H中求最小值  , 折纸策略最优是每次折半. 解题代码: 1 // BEGIN CUT HERE 2 /* 3 4 */ 5 // END CUT HERE 6 #line 7 "FoldingPaper2.cpp" 7 #include <cstdlib> 8 #include <cctype> 9 #incl

Topcoder SRM 563 Div1 500 SpellCards

题意 [题目链接]这怎么发链接啊..... 有\(n\)张符卡排成一个队列,每张符卡有两个属性,等级\(li\)和伤害\(di\). 你可以做任意次操作,每次操作为以下二者之一: 把队首的符卡移动到队尾. 使用队首的符卡,对敌人造成\(d_i\)点伤害,并丢弃队首的\(l_i\)张符卡(包括你所使用的符卡).如果队列不足\(l_i\)张符卡那么你不能使用. 求出造成的伤害的总和的最大值. \(1<=n<=50, 1<=li<=50, 1<=di<=10000\) Sol

TopCoder SRM500 Div1 250 其他

原文链接https://www.cnblogs.com/zhouzhendong/p/SRM500-250.html SRM500 Div1 250 题意 (看题用了半个小时--) 有 n 个人(编号从 0 到 n-1)玩游戏,要通过投票的方式确定谁输.现在已知有一些人有明确的意见,认为谁输.具体地用一个 vector decision 来描述,vector decision 的大小可能不足 n . 定义一个集合 S 包含一些人,初始的时候集合 S 包含所有人.他们会进行若干轮投票,每一轮中,一

TopCoder 649 div1 &amp; div2

最近一场TC,做得是在是烂,不过最后challenge阶段用一个随机数据cha了一个明显错误的代码,最后免于暴跌rating,还涨了一点.TC题目质量还是很高的,非常锻炼思维,拓展做题的视野,老老实实补题吧. div2 250pts 题意:判断s去掉一个字符后能否和t一样. 代码: 1 class DecipherabilityEasy { 2 public: 3 string check(string s, string t) { 4 int n = s.size(); 5 int m = t

TopCoder 603 div1 &amp; div2

div2 250pts MiddleCode 题意:s串长度为奇数时,将中间字符取掉并添加到t末尾:长度为偶数时,将中间两个较小的字符取掉并添加到末尾. 分析:直接做,学习了一下substr(s, pos, len)返回s中从pos开始的长度为len的字串. 代码: 1 class MiddleCode { 2 public: 3 void Remove(string &s, int pos) { 4 int len = s.size(); 5 string t = ""; 6