SRM 502(2-1000pt)

题意:在0~(n-1)中选择k个数,使得他们的和为n的倍数的选择方案有多少种。(n <= 1000, k <= 47)

解法:裸dp。d[i][j][k’]表示在前i个数中(0~i-1),选择k‘个数使得其和mod n的余数为j的选择方案的种数。时间、空间复杂度均为O(n^2*k),时间复杂度能接受,空间不能,用滚动数组优化即可。

tag:dp, 水题

  1 // BEGIN CUT HERE
  2 /*
  3  * Author:  plum rain
  4  * score :
  5  */
  6 /*
  7 
  8  */
  9 // END CUT HERE
 10 #line 11 "TheCowDivTwo.cpp"
 11 #include <sstream>
 12 #include <stdexcept>
 13 #include <functional>
 14 #include <iomanip>
 15 #include <numeric>
 16 #include <fstream>
 17 #include <cctype>
 18 #include <iostream>
 19 #include <cstdio>
 20 #include <vector>
 21 #include <cstring>
 22 #include <cmath>
 23 #include <algorithm>
 24 #include <cstdlib>
 25 #include <set>
 26 #include <queue>
 27 #include <bitset>
 28 #include <list>
 29 #include <string>
 30 #include <utility>
 31 #include <map>
 32 #include <ctime>
 33 #include <stack>
 34 
 35 using namespace std;
 36 
 37 #define CLR(x) memset(x, 0, sizeof(x))
 38 #define PB push_back
 39 #define SZ(v) ((int)(v).size())
 40 #define zero(x) (((x)>0?(x):-(x))<eps)
 41 #define out(x) cout<<#x<<":"<<(x)<<endl
 42 #define tst(a) cout<<#a<<endl
 43 #define CINBEQUICKER std::ios::sync_with_stdio(false)
 44 
 45 typedef vector<int> VI;
 46 typedef vector<string> VS;
 47 typedef vector<double> VD;
 48 typedef long long int64;
 49 
 50 const double eps = 1e-8;
 51 const double PI = atan(1.0)*4;
 52 const int maxint = 2139062143;
 53 const int mod = 1000000007;
 54 
 55 int d[2][1005][50];
 56 
 57 class TheCowDivTwo
 58 {
 59     public:
 60         int find(int n, int K){
 61             CLR (d);
 62             d[0][0][0] = 1;
 63             int cur = 1;
 64             for (int i = 1; i <= n; ++ i){
 65                 for (int j = 0; j < n; ++ j){
 66                     int tmp = j-(i-1)<0 ? n+j-(i-1) : j-(i-1);
 67                     for (int k = 0; k <= K; ++ k){
 68                         d[cur][j][k] = d[cur^1][j][k];
 69                         if (k){
 70                             d[cur][j][k] = (d[cur][j][k] + d[cur^1][tmp][k-1]) % mod;
 71                         }
 72                     }
 73                 }
 74                 cur ^= 1;
 75             }
 76 
 77             return d[cur^1][0][K];
 78         }
 79         
 80 // BEGIN CUT HERE
 81     public:
 82     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(); }
 83     private:
 84     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(); }
 85     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; } }
 86     void test_case_0() { int Arg0 = 7; int Arg1 = 4; int Arg2 = 5; verify_case(0, Arg2, find(Arg0, Arg1)); }
 87     void test_case_1() { int Arg0 = 1; int Arg1 = 1; int Arg2 = 1; verify_case(1, Arg2, find(Arg0, Arg1)); }
 88     void test_case_2() { int Arg0 = 58; int Arg1 = 4; int Arg2 = 7322; verify_case(2, Arg2, find(Arg0, Arg1)); }
 89     void test_case_3() { int Arg0 = 502; int Arg1 = 7; int Arg2 = 704466492; verify_case(3, Arg2, find(Arg0, Arg1)); }
 90     void test_case_4() { int Arg0 = 1000; int Arg1 = 47; int Arg2 = 219736903; verify_case(4, Arg2, find(Arg0, Arg1)); }
 91 
 92 // END CUT HERE
 93 
 94 };
 95 
 96 // BEGIN CUT HERE
 97 int main()
 98 {
 99 //    freopen( "a.out" , "w" , stdout );    
100     TheCowDivTwo ___test;
101     ___test.run_test(-1);
102        return 0;
103 }
104 // END CUT HERE
View Code

 

posted @ 2013-12-09 10:47  Plumrain  阅读(233)  评论(0编辑  收藏  举报