SRM 403(1-250pt, 1-500pt)

DIV1 250pt

题意:称各个数位只含有4和7的数为lucky number,给定a,b,求[a, b]中的lucky number有多少个。a, b <= 10^9

解法:很明显的数位dp,写出来也就20行左右。本来以为最近刚好在做数位dp,可以很快出,结果我想着刚才做的那个数位dp,脑袋进水居然直接敲了段递归的代码还半天没调出来.......然后很快写了段非递归的代码过了.....160score...

   后来看官方题解说,由于10^9内实际上只有1022个lucky number,所以可以求全部生成出来,看有哪些在[a, b]上。

tag:数位dp,think

  1 // BEGIN CUT HERE
  2 /*
  3  * Author:  plum rain
  4  * score :
  5  */
  6 /*
  7 
  8  */
  9 // END CUT HERE
 10 #line 11 "TheLuckyNumbers.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 CLR1(x) memset(x, -1, sizeof(x))
 39 #define PB push_back
 40 #define SZ(v) ((int)(v).size())
 41 #define ALL(t) t.begin(),t.end()
 42 #define zero(x) (((x)>0?(x):-(x))<eps)
 43 #define out(x) cout<<#x<<":"<<(x)<<endl
 44 #define tst(a) cout<<#a<<endl
 45 #define CINBEQUICKER std::ios::sync_with_stdio(false)
 46 
 47 typedef vector<int> VI;
 48 typedef vector<string> VS;
 49 typedef vector<double> VD;
 50 typedef pair<int, int> pii;
 51 typedef long long int64;
 52 
 53 const double eps = 1e-8;
 54 const double PI = atan(1.0)*4;
 55 const int maxint = 2139062143;
 56 
 57 int dit[20], two[20];
 58 
 59 int gao(int x)
 60 {
 61     two[0] = 1;
 62     for (int i = 1; i < 15; ++ i)
 63         two[i] = two[i-1] * 2;
 64 
 65     int len = 0;
 66     while (x){
 67         dit[len++] = x % 10;
 68         x /= 10;
 69     }
 70 
 71     int ret = 0;
 72     for (int i = 1; i < len; ++ i)
 73         ret += two[i];
 74     for (int i = len-1; i >= 0; -- i){
 75         if (4 < dit[i]) ret += two[i];
 76         if (7 < dit[i]) ret += two[i];
 77         if (dit[i] != 4 && dit[i] != 7) break;
 78     } 
 79     return ret;
 80 }
 81 
 82 class TheLuckyNumbers
 83 {
 84     public:
 85         int count(int a, int b){
 86             return gao(b+1) - gao(a);
 87         }
 88         
 89 // BEGIN CUT HERE
 90     public:
 91     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(); }
 92     private:
 93     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(); }
 94     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 << "	Expected: "" << Expected << '"' << endl; cerr << "	Received: "" << Received << '"' << endl; } }
 95     void test_case_0() { int Arg0 = 1; int Arg1 = 1000000000; int Arg2 = 1022; verify_case(0, Arg2, count(Arg0, Arg1)); }
 96     void test_case_1() { int Arg0 = 11; int Arg1 = 20; int Arg2 = 0; verify_case(1, Arg2, count(Arg0, Arg1)); }
 97     void test_case_2() { int Arg0 = 74; int Arg1 = 77; int Arg2 = 2; verify_case(2, Arg2, count(Arg0, Arg1)); }
 98     void test_case_3() { int Arg0 = 1000000; int Arg1 = 5000000; int Arg2 = 64; verify_case(3, Arg2, count(Arg0, Arg1)); }
 99 
100 // END CUT HERE
101 
102 };
103 
104 // BEGIN CUT HERE
105 int main()
106 {
107 //    freopen( "a.out" , "w" , stdout );    
108     TheLuckyNumbers ___test;
109     ___test.run_test(-1);
110        return 0;
111 }
112 // END CUT HERE
View Code

DIV1 500pt

题意:称各个数位只含有4和7的数为lucky number,称完全由来自vector<int> numbers(含有lucky number和也含有unlucky number)里面的lucky number组成,且每一个a[i]的末位数字和a[i+1]的首位数字均相同的序列为lucky sequence。给定vector<int> numbers和int n,求长度为n的lucky sequence有多少个。只要一个数不同,则lucky sequence视为不同。

解法:lucky number分为四种,分别为4开头4结尾的,4开头7结尾的,7开头4结尾的,7开头7结尾的。若a[i]属于第A类,且a[i+1]可以为B类,则从A向B连接一条有向边。这样,就相当于求长度为n的路径有多少条。

   我最初的想法是二分,设f(x, s, e)表示求长度为x,从s类开始,从e类结束的路径有多少条,f(x, s, e)由 f(x/2, s, i) 和 f(x-x/2, i, e)求得。我以为这样二分以后时间复杂度降低了,实际上每次二分都有4个决策,时间复杂度反而提升了,于是我毫无悬念地TLE了。然后,我改了代码,把x / 2变成了x / 10000,即将x分为10001段来求,由于前面每一段长度均为x/10000,后面一段长度为x - x/10000,所以实际上只需要求20个东西,这样时间复杂度就降低到能接受的范围了。

   虽然算是水过了这道题,还是蛮开心的.....

   官方题解给出的方法是用矩阵快速幂优化。其实要构造这个并不难吧。。。当时想了一下用矩阵,怎么就没想出来呢。。。。

tag:矩阵乘法

  1 // BEGIN CUT HERE
  2 /*
  3  * Author:  plum rain
  4  * score :
  5  */
  6 /*
  7 
  8  */
  9 // END CUT HERE
 10 #line 11 "TheLuckySequence.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 CLR1(x) memset(x, -1, sizeof(x))
 39 #define PB push_back
 40 #define SZ(v) ((int)(v).size())
 41 #define ALL(t) t.begin(),t.end()
 42 #define zero(x) (((x)>0?(x):-(x))<eps)
 43 #define out(x) cout<<#x<<":"<<(x)<<endl
 44 #define tst(a) cout<<#a<<endl
 45 #define CINBEQUICKER std::ios::sync_with_stdio(false)
 46 
 47 typedef vector<int> VI;
 48 typedef vector<string> VS;
 49 typedef vector<double> VD;
 50 typedef pair<int, int> pii;
 51 typedef long long int64;
 52 
 53 const double eps = 1e-8;
 54 const double PI = atan(1.0)*4;
 55 const int maxint = 2139062143;
 56 const int mod = 1234567891;
 57 
 58 int64 cnt[4];
 59 pii temp[4];
 60 set<int> st;
 61 int64 pat[4][4], d[40000][4][4];
 62 int64 an[40000][4];
 63 
 64 int gao(int x)
 65 {
 66     pii num;
 67     num.second = x % 10;
 68     while (x >= 10){
 69         int tmp = x % 10;
 70         x /= 10;
 71         if (tmp != 7 && tmp != 4) return -1;
 72     }
 73     num.first = x % 10;
 74     for (int i = 0; i < 4; ++ i)
 75         if (num == temp[i]) return i;
 76     return -1;
 77 }
 78 
 79 int64 rec(int len, int s, int e)
 80 {
 81     if (!len) return s == e;
 82     if (len == 1) return pat[s][e];
 83     
 84     if (len < 40000 && d[len][s][e] != -1)
 85         return d[len][s][e];
 86 
 87     if (len < 40000){
 88         int haf = len / 2;
 89         int64 &ret = d[len][s][e];
 90         ret = 0;
 91         for (int i = 0; i < 4; ++ i)
 92             ret = (ret + rec(haf, s, i) * rec(len-haf, i, e)) % mod;
 93         return ret;
 94     }
 95 
 96     int haf = len / 40000;
 97     CLR (an);
 98     for (int i = 0; i < 4; ++ i)
 99         an[0][i] = rec(haf, s, i);
100     for (int i = 1; i < 40000; ++ i)
101         for (int j = 0; j < 4; ++ j)
102             for (int k = 0; k < 4; ++ k)
103                 an[i][j] = (an[i][j] + an[i-1][k] * rec(haf, k, j)) % mod;
104     int64 ret = 0;
105     for (int i = 0; i < 4; ++ i)
106         ret = (ret + an[39999][i] * rec(len-haf*40000, i, e)) % mod; 
107     return ret;
108 }
109 
110 class TheLuckySequence
111 {
112     public:
113         int count(vector <int> num, int len){
114             temp[0] = make_pair(4,4); temp[1] = make_pair(4,7);
115             temp[2] = make_pair(7,4); temp[3] = make_pair(7,7);
116 
117             CLR (cnt); st.clear();
118             for (int i = 0; i < (int)num.size(); ++ i){ 
119                 int tmp = gao(num[i]);
120                 if (tmp != -1 && !st.count(num[i])){
121                     ++ cnt[tmp];
122                     st.insert(num[i]);
123                 }
124             }
125             CLR (pat);
126             for (int i = 0; i < 4; ++ i)
127                 for (int j = 0; j < 4; ++ j)
128                     if (temp[i].second == temp[j].first){
129                         pat[i][j] = cnt[i];
130                     }
131 
132             CLR1 (d);
133             int64 ret = 0;
134             for (int i = 0; i < 4; ++ i)
135                 for (int j = 0; j < 4; ++ j)
136                     ret = (ret + rec(len-1, i, j) * cnt[j]) % mod;
137             return (int)ret;
138         }
139         
140 // BEGIN CUT HERE
141     public:
142     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(); }
143     private:
144     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(); }
145     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 << "	Expected: "" << Expected << '"' << endl; cerr << "	Received: "" << Received << '"' << endl; } }
146     void test_case_0() { int Arr0[] = {44, 47, 74, 77, 44, 47, 74, 77}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arg1 = 1000000000; int Arg2 = 1133762585; verify_case(0, Arg2, count(Arg0, Arg1)); }
147     void test_case_1() { int Arr0[] = {47, 74, 47}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arg1 = 3; int Arg2 = 2; verify_case(1, Arg2, count(Arg0, Arg1)); }
148     void test_case_2() { int Arr0[] = {100, 4774, 200, 747, 300}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arg1 = 47; int Arg2 = 2; verify_case(2, Arg2, count(Arg0, Arg1)); }
149     void test_case_3() { int Arr0[] = {44, 47, 74, 77}; vector <int> Arg0(Arr0, Arr0 + (sizeof(Arr0) / sizeof(Arr0[0]))); int Arg1 = 2; int Arg2 = 8; verify_case(3, Arg2, count(Arg0, Arg1)); }
150 
151 // END CUT HERE
152 
153 };
154 
155 // BEGIN CUT HERE
156 int main()
157 {
158 //    freopen( "a.out" , "w" , stdout );    
159     TheLuckySequence ___test;
160     ___test.run_test(-1);
161        return 0;
162 }
163 // END CUT HERE
View Code
原文地址:https://www.cnblogs.com/plumrain/p/srm_403.html