CodeForces 855E Salazar Slytherin's Locket(数位dp+搜索剪枝)

来源:互联网 发布:知微数据 编辑:程序博客网 时间:2024/06/06 02:32

Salazar Slytherin's Locket

time limit per test:2 seconds

memory limit per test:256 megabytes

input:standard input

output:standard output

Harry came to know from Dumbledore that Salazar Slytherin's locket is a horcrux. This locket was present earlier at 12 Grimmauld Place, the home of Sirius Black's mother. It was stolen from there and is now present in the Ministry of Magic in the office of Dolorous Umbridge, Harry's former Defense Against the Dark Arts teacher.

Harry, Ron and Hermione are infiltrating the Ministry. Upon reaching Umbridge's office, they observed a code lock with a puzzle asking them to calculate count of magic numbers between two integersl and r (both inclusive).

Harry remembered from his detention time with Umbridge that she defined a magic number as a number which when converted to a given baseb, all the digits from 0 to b - 1 appear even number of times in its representation without any leading zeros.

You have to answer q queries to unlock the office. Each query has three integersbi,li andri, the base and the range for which you have to find the count of magic numbers.

Input

First line of input contains q (1 ≤ q ≤ 105) — number of queries.

Each of the next q lines contain three space separated integersbi,li,ri (2 ≤ bi ≤ 10,1 ≤ li ≤ ri ≤ 1018).

Output

You have to output q lines, each containing a single integer, the answer to the corresponding query.

Examples
Input
22 4 93 1 10
Output
12
Input
22 1 1005 1 100
Output
214

Note

In sample test case 1, for first query, when we convert numbers4 to 9 into base 2, we get:

  • 4 = 1002,
  • 5 = 1012,
  • 6 = 1102,
  • 7 = 1112,
  • 8 = 10002,
  • 9 = 10012.

Out of these, only base 2 representation of 9 has even number of 1 and 0. Thus, the answer is 1.



        又是一道数位dp。

        大致题意是给你一个进制b,然后问你区间[l,r]之间的数字,转换为b进制之后,有多少个数字满足,0~b-1中的每一个数字出现在每一位的次数是偶数。

        其实这里加了一个进制,无非就是多了一维表示不同进制,然后分解数字时按照进制分解,枚举每一位数字时枚举到b-1而已。真正关键的还是状态的转移。这里考虑由于要每一个数字出现的次数为偶数,所以我们就可以用奇偶对应0、1来表示。由于最多是10进制,所以我们可以用一个10位的二进制数字来表示0~b-1这些数字出现的次数是奇数还是偶数,即用这个数字状态压缩表示数字出现的奇偶情况。当dp进行到底层时,判断最后的10位二进制数是否为0即可,如果为0那么找到一种合法方案,否则不合法。

        但是,这里有一个前导0的限制,其实这个很好解决,或者说必须不能把前导0算进去。为了解决这个问题,我们考虑在外层,先枚举我要统计的数字的长度,第一次进入的时候必须从1考试枚举,否则从0开始。换个角度来说,如果考虑前导0,那么首位可以填0,填0之后,0的出现次数为1,但实际上,我们认为此时0的出现次数应该是0,就出现了差错。所以从这个层面上说,即使题目没有要求,我们也得这样做特殊处理。

        按照这样的思路一阵敲打之后,你会发现,你得到的是一个大大的TLE,要么是在第9个T,要么是在第14个。按照复杂度来说,这个T是可以预料的,因为如果是2进制,那么最多63位,然后每一位可以取0和1,即使加上记忆化搜索也容易T,所以我们要考虑做一些剪枝。首先我们发现,长度为奇数的数字肯定不可能满足条件,因为长度为奇数,所以注定意味着有一个数字要单出来,所以不可能所有数字都是出现奇数次。其次,如果当前10位二进制数状态下,1的位数如果比剩余的可放数字的位数还要大,那么肯定不能填补回0,所以无合法方案。再次,如果当前1的位数与剩余位数奇偶性不同,那么也不可能有合法方案。用上这三条剪枝,最后可以在500MS左右的时间内把此题给过了。具体见代码:

#include<bits/stdc++.h>#define LL long long#define N 1100using namespace std;LL dp[11][64][N];int n,b,num[64];int check(int x){    int res=0;    for(;x;x>>=1) if (x&1) res++;    return res;}LL dfs(int len,int status,bool lim,bool first)//first表示是否是第一位,第一位得从1开始枚举{    if (len<1) return status==0;//如果最后的status为0,那么说明这是种合法方案    int times=check(status);//times为当前状态下1的个数    if (times>len) return 0;//如果1的个数比剩余可添加位数多,那么不存在可行方案    if ((times&1)^(len&1)) return 0;//如果奇偶性不同,那么不存在可行方案    if ((len&1)&&status==0) return 0;//如果剩下长度为奇数,且当前已经合法,那么不存在可行方案    if (dp[b][len][status]&&!lim&&!first) return dp[b][len][status];    int up=lim?num[len]:b-1; LL res=0;    for(int i=first;i<=up;i++)        res+=dfs(len-1,status^(1<<i),lim&&i==up,0);//每次添加数字,用异或改变对应的状态    if (!lim&&!first) dp[b][len][status]=res;    return res;}LL cal(LL x){    int tot=0;    for(;x;x/=b) num[++tot]=x%b;    LL res=0;    for(int i=1;i<=tot;i++)//枚举位数进行统计        res+=dfs(i,0,i==tot,1);    return res;}int main(){    int T_T;    cin>>T_T;    while(T_T--)    {        LL l,r;        scanf("%d%I64d%I64d",&b,&l,&r);        printf("%I64d\n",cal(r)-cal(l-1));    }    return 0;}

阅读全文
0 0
原创粉丝点击