Balanced Numbers(数位+状压)

时间:2023-03-09 20:15:20
Balanced Numbers(数位+状压)

题意:求给定区间,一个数的数位上每个奇数出现偶数次,每个偶数出现奇数次,这样数的个数

分析:先考虑状态,但总是想不全,所以要把状态压缩一下,用三进制,0 该数不放  1 放了奇数次 2放了偶数次

dp[i][j] 长度为i 状态是j的数字个数,需要前导0判断,前导0不能计入偶数出现的次数。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<11
#define All 1,N,1
#define read freopen("in.txt", "r", stdin)
const ll INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod = ;
ll dp[][],a,b;
int bit[],cas[];
//化三进制
void get(int x)
{
for(int i=; i<; ++i)
{
cas[i]=x%;
x/=;
}
}
//状态改变
int change(int x,int b)
{
get(x);
if(cas[b]==)
cas[b]=;
else if(cas[b]==)
cas[b]=;
else cas[b]=;
int s=,tmp=;
for(int i=; i<; ++i)
{
s+=cas[i]*tmp;
tmp*=;
}
return s;
}
//判断符合条件
int judge(int s)
{
get(s);
for(int i=; i<; ++i)
{
if(i%&&cas[i]==)return ;
if(i%==&&cas[i]==)return ;
}
return ;
}
ll dfs(int i,int j,int f,int e)
{
if(i==)return judge(j);
if(!e&&dp[i][j]!=-)return dp[i][j];
int u=e?bit[i]:;
ll num=;
for(int v=; v<=u; ++v)
{
if(f&&v==)
num+=dfs(i-,,,e&&(v==u));
else
{
num+=dfs(i-,change(j,v),,e&&(v==u));
}
}
if(!e)dp[i][j]=num;
return num;
}
ll solve(ll x)
{
int len=;
while(x)
{
bit[++len]=x%;
x/=;
}
return dfs(len,,,);
}
int main()
{
int t;
scanf("%d",&t);
memset(dp,-,sizeof(dp));
while(t--)
{
scanf("%I64d%I64d",&a,&b);
printf("%I64d\n",solve(b)-solve(a-));
}
return ;
}