855E

数位DP

昨天的B题,excited

又学习了一下数位dp...

数位dp要考虑几个比较重要的东西:1.前导0,2.天际线,3.记忆化的条件,4.细节

经常数位dp会问我们l->r区间中满足某某条件的数的个数,这个条件很明显满足可减性,所以一般转化为1->r的数-1->l-1的数,采用记忆化搜索的方式统计

这道题状态为dp[base][bit][state][pre],表示当前底数为base,统计的数有bit位,每种数出现次数用state表示,有没有前导0

然后考虑状态的改变,也就是前导0,天际线的变化,先考虑前导0的变化,如果当前放置的数不是0,那么前导0不存在,可以把这个数放进状态内,否则如果一直是前导0则不把前导0放入状态,前导0也要设进dp状态内;然后考虑天际线,我们先想一想所设的dp状态,dp[base][bit][state][pre],这是表示当前base下,这个数包括前导0,状态为state,有没有前导0,注意这个数是包括所有位数为bit的数,如果我们在记忆化搜索的时候碰到了天际线,也就是limit=1,那么我们不能对搜出的结果记忆化,也不能返回之前已经记忆化好的答案,因为天际线去除掉了一些数,而dp统计了所有长度为bit的数。

这样能够保证所有的数都被统计进去吗?是可以的,我们统计了天际线及以下长度为bit的数,但是那些长度小于bit的呢?其实我们把这些数转换为了加上前导零的数,这样就能很好地统计了。

所以数位dp我们要考虑1.前导0的变化,2.是否卡在天际线,3.dp状态不同情况下的变化,4.记忆化的条件,5.每次枚举第bit位是什么的范围,然后通过记忆化搜索实现。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int q;
ll dp[11][70][2048][2], f[20];
ll dfs(int base, int bit, int S, int pre, int limit) //flag = 2 超了 flag = 1正好 flag = 0 小了
{
    if(bit == 0) return !S;
    if(!limit && dp[base][bit][S][pre] != -1) return dp[base][bit][S][pre];
    ll ret = 0;
    int mx = limit ? f[bit] : base - 1;
    for(int i = 0; i <= mx; ++i)
    {
        if(i == 0 && pre) ret += dfs(base, bit - 1, S, pre, limit && (i == mx));
        else ret += dfs(base, bit - 1, S ^ (1 << i), 0, limit && (i == mx));
    }
    if(!limit) dp[base][bit][S][pre] = ret;
    return ret;
}
ll solve(int base, ll lim)
{
    f[0] = 0;
    while(lim)
    {
        f[++f[0]] = lim % base;
        lim /= base;
    }
    return dfs(base, f[0], 0, 1, 1);
}
int main()
{
    memset(dp, -1, sizeof(dp));
    scanf("%d", &q);
    while(q--)
    {
        int base;
        ll l, r;
        scanf("%d%lld%lld", &base, &l, &r);
        printf("%lld\n", solve(base, r) - solve(base, l - 1));
    }
    return 0;
}

时间: 2024-10-08 02:37:20

855E的相关文章

Salazar Slytherin&#39;s Locket CodeForces - 855E

Salazar Slytherin's Locket CodeForces - 855E http://www.cnblogs.com/ftae/p/7590187.html 数位dp: http://www.cnblogs.com/xz816111/p/4809913.html http://blog.csdn.net/wust_zzwh/article/details/52100392 1. 1 #include<cstdio> 2 #include<cstring> 3 ty

JS中URL编码参数(UrlEncode)

网上有很多文字作品写涉及在JS中呈现类似UrlEncode功能时都是自定义参数来呈现,其实JS中本身就有那样的参数.参数parameter由于用类似URL的形式传过去 , 所以别直接就那样赋值以下是对变量值的URL编码总结 : 意见用encodeURIComponent() , GET 和POST方法都能够发送过去Java编程script中存在几种对URL字符串停止编码的窍门:escape(),encodeURI(),以及encodeURIComponent().这几种编码所起的功能各不相同.e

GBK UTF-16 UTF-8 编码表

GBK   UTF-16 UTF-8 ================== D2BB  4E00  E4 B8 80  一 B6A1  4E01  E4 B8 81  丁 C6DF  4E03  E4 B8 83  七 CDF2  4E07  E4 B8 87  万 D5C9  4E08  E4 B8 88  丈 C8FD  4E09  E4 B8 89  三 C9CF  4E0A  E4 B8 8A  上 CFC2  4E0B  E4 B8 8B  下 D8A2  4E0C  E4 B8 8C

JS base64 加密和 后台 base64解密(防止中文乱码)

直接上代码 1,js(2个文件,网上找的)  不要觉的长,直接复制下来就OK //UnicodeAnsi.js文件 //把Unicode转成Ansi和把Ansi转换成Unicode function UnicodeChr() { return '00A4,00A7,00A8,00B0,00B1,00B7,00D7,00E0,00E1,00E8,00E9,00EA,00EC,00ED,00F2,00F3,00F7,00F9,00FA,00FC,0101,0113,011B,012B,014D,01

Html5模拟通讯录人员排序(sen.js)

// JavaScript Document var PY_Json_Str = ""; var PY_Str_1 = ""; var PY_Str_2 = "";  var PY_Str_3 = "";  var PY_Str_4 = ""; var PY_Str_5 = ""; var PY_Str_6 = "";  var PY_Str_7 = "&q

MFC简单的橡皮筋程序

网上有很多文字作品写涉及在JS中呈现类似UrlEncode功能时都是自定义参数来呈现,其实JS中本身就有那样的参数.参数parameter由于用类似URL的形式传过去 , 所以别直接就那样赋值以下是对变量值的URL编码总结 : 意见用encodeURIComponent() , GET 和POST方法都能够发送过去Java编程script中存在几种对URL字符串停止编码的窍门:escape(),encodeURI(),以及encodeURIComponent().这几种编码所起的功能各不相同.e

将able导出为excel格式文件

html: <table cellpadding="0" cellspacing="0" class="data_table" id="data_table"> <tr> <th>日期</th> <th>星期</th> <th>渠道</th> <th>服务区</th> <th>总用户</th

python 判断是否为中文

python在执行代码过程是不知道这个字符是什么意思的.是否是中文,而 是把所有代码翻译成二进制也就是000111这种形式,机器可以看懂的语言. 也就是在计算机中所有的字符都是有数字来表示的.汉字也是有数字表示的, Unicdoe4E00~9FFF表示中文,所以如果一个字符的utf-8编码在这个区间内,就 说明它是中文. 代码: def is_Chinese(word): for ch in word: if '\u4e00' <= ch <= '\u9fff': return True re