• [HNOI2002] Kathy 函数


    数位 DP 套路题,求二进制下区间内回文串个数。

    设 dp[][][] 表示到第几位时,是否为回文数,去掉前导零后共几位。之后到边界时判断是否为回文数计入贡献。

    一开始不知道答案统计要高精,于是后来就自闭了。

    #include <cmath>
    #include <queue>
    #include <cstdio>
    #include <cctype>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    
    const int maxn = 350;
    int n, num[maxn], tmp[maxn]; char str[maxn], che[maxn][2][maxn];
    
    class Big_integer {
    private:
      int len, a[105];
    
    public:
      Big_integer() { memset(a, 0, sizeof a), len = 1; }
      ~Big_integer() {};
    
      inline bool operator == (const Big_integer &x) const {
        if( this->len != x.len ) return false;
        for(int i = len; i; --i) if( this->a[i] != x.a[i] ) return false;
        return true;
      }
    
      inline bool operator < (const Big_integer &x) const {
        if( this->len != x.len ) return this->len < x.len;
        for(int i = len; i; --i) if( this->a[i] > x.a[i] ) return false;
        return (*this == x) == false;
      }
    
      inline bool operator > (const Big_integer &x) const {
        if( this->len != x.len ) return this->len > x.len;
        for(int i = len; i; --i) if( this->a[i] < x.a[i] ) return false;
        return (*this == x) == false;
      }
    
      inline Big_integer operator = (int x) {
        memset(a, 0, sizeof a), len = 0;
        while( x ) a[++len] = x % 10, x = x / 10;
        return *this;
      }
    
      inline Big_integer operator + (const Big_integer &x) const {
        Big_integer res;
        res.len = max(this->len, x.len) + 1;
        for(int i = 1; i <= res.len; ++i) {
          res.a[i] = this->a[i] + x.a[i] + res.a[i];
          if( res.a[i] > 9 ) res.a[i + 1] = res.a[i] / 10, res.a[i] = res.a[i] % 10;
        }
        while( res.a[res.len] == 0 && res.len > 1 ) --res.len;
        return res;
      }
    
      inline Big_integer operator / (const int &x) const {
        Big_integer res;
        res.len = this->len;
        for(int r = 0, i = len; i; --i) res.a[i] = (r * 10 + this->a[i]) / x, r = (r * 10 + this->a[i]) % x;
        while( res.a[res.len] == 0 && res.len > 1 ) --res.len;
        return res;
      }
    
      inline void read() {
        scanf("%s", str + 1), len = strlen(str + 1);
        for(int i = len; i; --i) a[i] = str[len - i + 1] ^ 48;
      }
    
      inline void prin() {
        for(int i = len; i; --i) printf("%d", a[i]); printf("
    ");
      }
    
      inline void Transform(int *arr) {
        while( a[len] != 0 ) arr[++n] = a[1] & 1, *this = *this / 2;
      }
    } a, dp[maxn][2][maxn];
    
    inline Big_integer Deep_fs(int fir, int pos, int tag, int limit) {
      Big_integer res;
      if( pos < 1 ) return (tag && fir > 0) ? res = 1 : res = 0;
      if( limit == 0 && che[pos][tag][fir] ) return dp[pos][tag][fir];
      for(int i = 0; i <= (limit ? num[pos] : 1); ++i) {
        tmp[pos] = i;
        if( fir == pos && i == 0 ) res = res + Deep_fs(fir - 1, pos - 1, tag, limit && i == num[pos]);
        else res = res + Deep_fs(fir, pos - 1, (tag && pos <= (fir >> 1)) ? tmp[fir - pos + 1] == i : tag, limit && i == num[pos]);
      }
      if( limit == 0 ) dp[pos][tag][fir] = res, che[pos][tag][fir] = 1;
      return res;
    }
    
    int main(int argc, char const *argv[])
    {
      a.read(), a.Transform(num), Deep_fs(n, n, 1, 1).prin();
    
      return 0;
    }
    
  • 相关阅读:
    BZOJ4821 SDOI2017相关分析(线段树)
    BZOJ3167/BZOJ4824 HEOI2013SAO/CQOI2017老C的键盘(树形dp)
    BZOJ4820 SDOI2017硬币游戏(概率期望+高斯消元+kmp)
    BZOJ4811 Ynoi2017由乃的OJ(树链剖分+线段树)
    BZOJ4810 Ynoi2017由乃的玉米田(莫队+bitset)
    Codeforces Round #522 Div. 1 没打记
    BZOJ4784 ZJOI2017仙人掌(树形dp+dfs树)
    43. Multiply Strings
    2. Add Two Numbers
    150. Evaluate Reverse Polish Notation
  • 原文地址:https://www.cnblogs.com/nanjoqin/p/11318859.html
Copyright © 2020-2023  润新知