CodeForces 855E Salazar Slytherin's Locket

Salazar Slytherin's Locket

题解:

数位DP。

对于不同的进制直接数位DP就好了。

在数位dp中比较基础。

通过状压来xor值,使得表示每个数字出现奇数次/偶数次.

注意的就是 去除 00 0000 这些数的影响。

代码:

#include<bits/stdc++.h>
using namespace std;
#define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
#define LL long long
#define ULL unsigned LL
#define fi first
#define se second
#define pb push_back
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lch(x) tr[x].son[0]
#define rch(x) tr[x].son[1]
#define max3(a,b,c) max(a,max(b,c))
#define min3(a,b,c) min(a,min(b,c))
typedef pair<int,int> pll;
const int inf = 0x3f3f3f3f;
const int _inf = 0xc0c0c0c0;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const LL _INF = 0xc0c0c0c0c0c0c0c0;
const LL mod =  (int)1e9+7;
const int N = 2e5 + 100;
LL dp[11][80][2000][2];
///     k  len state
int sta[N];
LL dfs(int len, int state, int pre, int k, int lim){
    if(!lim && ~dp[k][len][state][pre])  return dp[k][len][state][pre];
    if(len == 0) return state == 0;
    int up = k - 1;
    if(lim) up = sta[len];
    LL ans = 0;
    for(int i = 0; i <= up; ++i){
        if(pre == 0 && len != 1 && i == 0) ans += dfs(len-1, state, 0, k, lim && (i == up));
        else ans += dfs(len-1, state^(1<<i), 1, k, lim && (i==up));
    }
    if(!lim) dp[k][len][state][pre] = ans;
    return ans;
}
LL cal(LL x, int k){
    if(x == 0) return 0;
    int top = 0;
    while(x){
        sta[++top] = x % k;
        x /= k;
    }
    return dfs(top, 0, 0, k, 1);
}
int main(){
    memset(dp, -1, sizeof dp);
    int q;
    scanf("%d", &q);
    int b;
    LL l, r;
    while(q--){
        scanf("%d%lld%lld", &b, &l, &r);
        printf("%lld\n", cal(r, b) - cal(l-1, b));
    }
    return 0;
}
View Code

 

posted @ 2019-07-03 09:36  Schenker  阅读(209)  评论(0编辑  收藏  举报