Description
Balanced numbers have been used by mathematicians for centuries. A positive integer is considered a balanced number if:
-
Every even digit appears an odd number of times in its decimal representation
-
Every odd digit appears an even number of times in its decimal representation
For example, 77, 211, 6222 and 112334445555677 are balanced numbers while 351, 21, and 662 are not.
Given an interval [A, B], your task is to find the amount of balanced numbers in [A, B] where both A and B are included.
Input
The first line contains an integer T representing the number of test cases.
A test case consists of two numbers A and B separated by a single space representing the interval. You may assume that 1 <= A <= B <= 1019
Output
For each test case, you need to write a number in a single line: the amount of balanced numbers in the corresponding interval
Sample Input
2
1 1000
1 9
Sample Output
147
4
核心思想:
将0~9这十个数字在数位上出现过的次数看作一个整体状态并压缩成一个三进制数k。
三进制数k的第i位的取值有三种情况:
0:i 未出现
1:i 出现奇数次
2:i 出现偶数次
数位dp,根据位数和状态记忆。
代码如下:
#include<cstdio>
#include<iostream>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=20,M=6e4+20;
ll dp[N][M];
int p[N],b[N],cnt;
//z出现次数+1
int update(int k,int z)
{
int t=k,q=z;
while(q--)t/=3;
if(t%3==2)k-=b[z];
else k+=b[z];
return k;
}
//k的第i位为0表示i未出现,为1表示出现奇数次,为2表示出现偶数次
ll dfs(int pos,int k,bool lim)
{
if(!pos)
{
//奇数不能出现奇次,偶数不能出现偶次
while(k)
{
if(k%3==2)return 0;
k/=3;
if(k%3==1)return 0;
k/=3;
}
return 1;
}
if(!lim&&dp[pos][k]!=-1)
return dp[pos][k];
int end=lim?p[pos]:9,v=1;
ll ans=0;
//区分前导0
if(k)
ans+=dfs(pos-1,update(k,0),!end);
else
ans+=dfs(pos-1,0,0);
//1~end
for(int i=1;i<=end;i++)
ans+=dfs(pos-1,update(k,i),lim&&i==end);
if(!lim)
return dp[pos][k]=ans;
return ans;
}
ll fun(ll x)
{
ll ans=0,t=x;
//按位拆分
cnt=0;
while(t)
{
p[++cnt]=t%10;
t/=10;
}
return dfs(cnt,0,1);
}
int main()
{
int T;
cin>>T;
//初始化位权
b[0]=1;
for(int i=1;i<10;i++)
b[i]=b[i-1]*3;
//初始化dp
for(int i=0;i<N;i++)
for(int j=0;j<M;j++)
dp[i][j]=-1;
while(T--)
{
ll x,y;
scanf("%lld%lld",&x,&y);
printf("%lld\n",fun(y)-fun(x-1));
}
return 0;
}