zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    leetcode 1. Two Sum
    leetcode 168. Excel Sheet Column Title
    [LeetCode] Water and Jug Problem 水罐问题
    leetcode 80 Remove Duplicates from Sorted Array II
    leetcode 239. Sliding Window Maximum
    文件处理
    python网络编程 之 twisted
    ICMP & ping & traceroute
    Java String 转整形
    Java 字符数字得到整数
  • 原文地址:https://www.cnblogs.com/plumrain/p/srm_403.html
Copyright © 2011-2022 走看看