您的位置:首页 > 其它

SPOJ BALNUM Balanced Numbers 【数位DP】

2016-10-29 19:36 387 查看
题目:点击打开链接

题意:给定一个区间,求出满足以下条件的所有数的个数:数位为奇数的出现偶数次,数位为偶数的出现奇数次。

思路:显然用数位DP做,考虑到要保存已经出现的0~9的次数,可以考虑用三进制压缩状态,这个三进制数有十位,从左向右一次表示0~9的出现情况,数位为0表示还未出现,数位为1表示已出现奇数次,数位为2表示已出现偶数次,注意排除掉前导零的情况。本题区间范围有1e19,本题应用unsigned long long型数字,但是数据较水long long可过,另外要用llu输入,I64u会超时。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <stdio.h>
#include <iostream>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>
#include <queue>
#include <set>
#include <vector>
#include <map>
#define PR pair<int,int>
#define MP make_pair
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define sqr(x) ((x)*(x))
#define ll long long
#define ull unsigned long long
const ll INF = 9*1e18;
const int inf=0x3f3f3f3f;
const int M=200;
const int N=72;
const int MOD=1000000007;
const double eps=1e-10;
const double pi=acos(-1.0);
using namespace std;
int dig[22],hsh[11];//hsh数组预处理3^x的值
ull dp[22][60000];//3^10接近为60000
void init()
{
memset(dp,-1,sizeof(dp));
hsh[0]=1;
for(int i=1;i<10;i++)
hsh[i]=hsh[i-1]*3;
hsh[10]=inf;
}
int change(int num,int n)//将状态转换为三进制,并根据状态改变而重新计算其三进制值
{
int tmp=hsh
;
if(num%hsh[n+1]<2*tmp) num+=tmp;//取模为排除掉该位右边的所有数,只比较左边的数值
else num-=tmp;
return num;
}
int check(int num)
{
int cur=0;
while(num)
{
int tmp=num%3;
if(cur==0&&tmp==2||cur==1&&tmp==1) return 0;
num/=3;
cur^=1;
}
return 1;
}
ull dfs(int pos,int num,int lim,int first)
{
if(pos==-1) return check(num);
if(!lim&&dp[pos][num]!=-1) return dp[pos][num];
int upper=lim?dig[pos]:9;
ull res=0;
for(int i=0;i<=upper;i++)
{
if(i==0)
{
if(first) res+=dfs(pos-1,0,lim&&(i==upper),1);
else res+=dfs(pos-1,change(num,i),lim&&(i==upper),0);
}
else res+=dfs(pos-1,change(num,i),lim&&(i==upper),0);
}
if(!lim) dp[pos][num]=res;
return res;
}
ull calc(ull x)
{
int len=0;
while(x)
{
dig[len++]=x%10;
x/=10;
}
return dfs(len-1,0,1,1);
}
int main()
{
init();
ull l,r,T;
scanf("%llu",&T);
while(T--)
{
scanf("%llu%llu",&l,&r);
printf("%llu\n",calc(r)-calc(l-1));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: