zoukankan      html  css  js  c++  java
  • http://codeforces.com/contest/776/problem/G

     题意: 讲一个16进制的数字num的每一位拆分下来 也就是sum = $sigma(2 ^ a_i)$ 每一个a_i 都是不同的

    举个栗子: $1014_16$ 就是 $2^1 + 2 ^ 0 + 2 ^ 4$

    求得的sum是个十进制的数字 然后将sum和num都化为二进制进行异或,如果异或后的值小于num那么++ans

    现在题目是给出一个区间[l, r] 问这个区间内有多少个满足条件的数,也就是区间内ans的大小

    思路:

    贪心+数位dp, 定义三个状态 dp[mask1][mask2][len]

    mask1代表的是枚举二进制上的1,说的更清楚点就是 $2^mask1$ 枚举每个二进制位的1  mask1不会超过16的因为$sigma_{i = 0}^{15}{2^i} = 2^16-1$; 

    mask2代表的是不超过16位数字(2进制下)的十进制数 因为题目是给出了数据范围的限制的, 所以 mask[i] = mask[i]%65536

    len 表示的是数字的长度同样也就是枚举最后的16位

    状态转移是 dp[mask1][mask2][len] += $sigma_{i = 0}^{15}dp[max(mask1, i)][mask2*16 + i][len-1]$

    然后dfs进行记忆化搜索就可以了,这里不得不感叹一下,cf的评测机真心快。 我本地跑了好几秒,而题目的时限是2.5s 然而不影响AC

    最后上代码:

    #include <iostream>
    #include <string.h>
    #include <stdio.h>
    #include <algorithm>
    #include <map>
    #include <set>
    #include <vector>
    #include <stdlib.h>
    #include <math.h>
    #include <string>
    #include <stack>
    #include <queue>
    using namespace std;
    
    long long dp[16][65537][17];
    int position[1100005];
    int bit[200000];
    bool flag = false;
    
    long long max(long long a, long long b) {
        return (a > b ? a : b);
    }
    
    long long dfs(long m, long long p, long long pos) {
    //    cout << m << ends << p << ends << pos << endl;
        if (dp[m][p][pos] != -1) {
            return dp[m][p][pos];
        }
        if (pos == 0) {
            //return (dp[m][p][pos] = !!((1 << m) & p));
            if ((1 << m)&p) dp[m][p][pos] = 1;
            else dp[m][p][pos] = 0;
            return dp[m][p][pos];
        }
        dp[m][p][pos] = 0;
        for (int i = 0; i < 16; ++i)
            dp[m][p][pos] += dfs(max(m, i), position[p*16+i], pos-1);
        return dp[m][p][pos];
    }
    
    long long calc(string s) {
        int len = s.length();
        long long sum = 0ll;
        for (int i = 0; i < len; ++i) {
            sum *= 16;
            if (s[i] >= '0' && s[i] <= '9') sum += s[i] - '0';
            else sum += s[i] - 'a' + 10;
        }
        if (flag) --sum;
        for (int i = 0; i < len; ++i) {
            bit[i] = sum % 16;
            sum /= 16;
        }
        long long ans = 0; int m = 0, p = 0;
        for (int i = len - 1; i >= 0; --i) {
            for (int j = 0; j < bit[i]; ++j) {
                ans += dp[max(m, j)][position[p*16 + j]][i];
            }
            m = max(m, bit[i]);
            p = position[p * 16 + bit[i]];
        }
        ans += dp[m][p][0];
        return ans;
    }
    
    void solveG() {
        int q; cin >> q;
        while (q-->0) {
            flag = false;
            string left; cin >> left;
            string right; cin >> right;
            long long ans = calc(right);
            flag = true;
            ans -= calc(left);
            cout << ans << endl;
        }
    }
    
    int main() {
        ios::sync_with_stdio(false);
        memset(dp, -1, sizeof dp);
        position[0] = 0;
        for (int i = 1; i <= 1100005; ++i) {
            position[i] = position[i - 1] + 1;
            if (position[i] == 65536)
                position[i] = 0;
        }
        dfs(0, 0, 16);
        solveG();
        return 0;
    }
    View Code
  • 相关阅读:
    Spring 学习笔记
    Java Web整合开发(33) -- SSH和SSJ
    2、常用操作
    jsonp使用
    PHP curl 封装 GET及POST方法很不错的
    浅谈CSRF攻击方式 转
    谷歌插件请求ci 解决CI框架的Disallowed Key Characters错误提示
    phpstorm10.0.3 下载与激活
    Mysql全文搜索match against的用法
    CentOS 6.4下编译安装MySQL 5.6.14 (转)
  • 原文地址:https://www.cnblogs.com/boson-is-god/p/6489272.html
Copyright © 2011-2022 走看看