首页 > 其他 > 详细

Balanced Numbers SPOJ - BALNUM

时间:2021-05-30 15:31:07      阅读:6      评论:0      收藏:0      [点我收藏+]

原题链接
考察:数位dp+状压dp
思路:
??因为要求每个数字的出现次数,我们只能把所有数字的出现次数记下来.因为数字比较少考虑状压.有三种状态:
0:没出现过
1:出现奇数次
2:出现偶数次
??这道题的状压dp预处理并根据情况计数感觉不是很好实现,如果用记忆化搜索我们只需要到终点看是否合法就行.注意前导零的情况.

Code

#include <iostream> 
#include <cstring>
#include <vector>
using namespace std;
typedef long long LL;
const int N = 21,M = 59060,S = 11;
int bit[S],pre[M][N>>1],a[N];
LL f[N][M];
bool st[M];
void init()
{
	bit[0] = 1; st[0] = 1;
	for(int i=1;i<S;i++) bit[i] = bit[i-1]*3;
	for(int i=1;i<59049;i++)
	{
		int t = i; bool ok = 1;
		for(int j=0;j<10;j++)
		{
			pre[i][j] = t%3,t/=3;
			if(pre[i][j])
			{
				if((j&1)&&pre[i][j]%2!=0) ok = 0;
				else if(!(j&1)&&pre[i][j]%2==0) ok = 0; 
			}
		}
		st[i] = ok;
	}
}
int get(int sta,int x)//第x位++ 
{
	if(pre[sta][x]<=1) return sta+bit[x];
	else return sta-bit[x]; 
}
LL dfs(int pos,int sta,bool limit,bool lead)
{
	if(!pos) return st[sta];
	if(!lead&&!limit&&f[pos][sta]!=-1) return f[pos][sta];
	int len = limit?a[pos]:9;
	LL res = 0;
	for(int i=0;i<=len;i++)
	{
		if(lead&&!i) res+=dfs(pos-1,sta,limit&&i==len,lead); 
		else res+=dfs(pos-1,get(sta,i),limit&&i==len,lead&&i==0);
	}
	if(!limit&&!lead) f[pos][sta] = res;
	return res;
}
LL dp(LL n)
{
	if(!n) return 1;
	int cnt = 0;
	while(n) a[++cnt] = n%10,n/=10;
	return dfs(cnt,0,1,1);
}
int main()
{
	int T;
	scanf("%d",&T);
	memset(f,-1,sizeof f);
	init();
	while(T--)
	{
		LL l,r; scanf("%lld%lld",&l,&r);
		printf("%lld\n",dp(r)-dp(l-1));
	}
	return 0;
}

Balanced Numbers SPOJ - BALNUM

原文:https://www.cnblogs.com/newblg/p/14827495.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!