Salazar Slytherin's Locket
题解
很水的一道数位dp。
在b进制下保证每个数的出现次数为偶,由于需要记录每个数出现次数的奇偶,而,很容易想到用状压来表示。
至于答案还是很常规的差分套路,用记忆化搜索来进行数位dp来求出小于等于某个数的满足条件数的个数。
令为进制下,在第位时状态为时满足条件数的个数。
转移时还是用记忆化搜索进行,转移方程也很好想。
源码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> pii;
const LL mo=1e9+7;
LL q,b,l[75],r[75],L,R,ans,dp[15][75][2205];
LL dfs(LL typ,int id,LL s,bool lim,bool pre){
if(!id)return !s;LL up=lim?r[id]:b-1,sum=0;
if(dp[typ][id][s]>=0&&!lim&&!pre)return dp[typ][id][s];
for(int i=up;i>=0;i--){
if(pre&&(!i)){sum+=dfs(typ,id-1,s,(i==r[id])&lim,1);continue;}
sum+=dfs(typ,id-1,s^(1<<i),(i==r[id])&lim,0);
}
if(lim|pre)return sum;return dp[typ][id][s]=sum;
}
signed main(){
memset(dp,-1,sizeof(dp));
scanf("%lld",&q);
while(q--){
scanf("%lld %lld %lld",&b,&L,&R);L--;
for(int i=1;i<=64;i++){
l[i]=L%b;L/=b;
r[i]=R%b;R/=b;
}
ans=dfs(b,64,0,1,1);
for(int i=1;i<=64;i++)r[i]=l[i];
printf("%lld\n",ans-dfs(b,64,0,1,1));
}
return 0;
}