spoj10606 数位dp (求出现的数字,所有偶数出现奇数次,所有奇数出现偶数次)
2015-02-24 11:41
399 查看
http://www.spoj.com/problems/BALNUM/
Balanced numbers have been used by mathematicians for centuries. A positive integer is considered a balanced number if:
1) Every even digit appears an odd number of times in its decimal representation
2) 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.
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
For each test case, you need to write a number in a single line: the amount of balanced numbers in the corresponding interval
/**
spoj10606 数位dp (求出现的数字,所有偶数出现奇数次,所有奇数出现偶数次)
解题思路:3进制表示数字0~9的出现情况,0表示没有出现,1表示奇数次,2表示偶数次
*/
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
LL dp[20][60000];
int bit[20];
bool check(int s)
{
int num[10];
for(int i=0;i<10;i++)
{
num[i]=s%3;
s/=3;
}
for(int i=0;i<10;i++)
{
if(num[i]!=0)
{
if(i%2==0&&num[i]==2)return false;
if(i%2==1&&num[i]==1)return false;
}
}
return true;
}
int getnews(int x,int s)
{
int num[10];
for(int i=0;i<10;i++)
{
num[i]=s%3;
s/=3;
}
if(num[x]==0)
num[x]=1;
else
num[x]=3-num[x];
int news=0;
for(int i=9;i>=0;i--)
{
news*=3;
news+=num[i];
}
return news;
}
LL dfs(int pos,int s,int flag,int z)
{
if(pos==-1)return check(s);
if(!flag&&dp[pos][s]!=-1)
return dp[pos][s];
LL ans=0;
int end=flag?bit[pos]:9;
for(int i=0;i<=end;i++)
{
ans+=dfs(pos-1,(z&&i==0)?0:getnews(i,s),flag&&i==end,z&&i==0);
}
if(!flag)dp[pos][s]=ans;
return ans;
}
LL solve(LL n)
{
int len=0;
while(n)
{
bit[len++]=n%10;
n/=10;
}
return dfs(len-1,0,1,1);
}
int main()
{
int T;
memset(dp,-1,sizeof(dp));
LL a,b;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&a,&b);
printf("%lld\n",solve(b)-solve(a-1));
}
return 0;
}
SPOJ Problem Set (classical)10606. Balanced NumbersProblem code: BALNUM |
1) Every even digit appears an odd number of times in its decimal representation
2) 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
Example
Input: 2 1 1000 1 9
Output: 147 4
/**
spoj10606 数位dp (求出现的数字,所有偶数出现奇数次,所有奇数出现偶数次)
解题思路:3进制表示数字0~9的出现情况,0表示没有出现,1表示奇数次,2表示偶数次
*/
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long LL;
LL dp[20][60000];
int bit[20];
bool check(int s)
{
int num[10];
for(int i=0;i<10;i++)
{
num[i]=s%3;
s/=3;
}
for(int i=0;i<10;i++)
{
if(num[i]!=0)
{
if(i%2==0&&num[i]==2)return false;
if(i%2==1&&num[i]==1)return false;
}
}
return true;
}
int getnews(int x,int s)
{
int num[10];
for(int i=0;i<10;i++)
{
num[i]=s%3;
s/=3;
}
if(num[x]==0)
num[x]=1;
else
num[x]=3-num[x];
int news=0;
for(int i=9;i>=0;i--)
{
news*=3;
news+=num[i];
}
return news;
}
LL dfs(int pos,int s,int flag,int z)
{
if(pos==-1)return check(s);
if(!flag&&dp[pos][s]!=-1)
return dp[pos][s];
LL ans=0;
int end=flag?bit[pos]:9;
for(int i=0;i<=end;i++)
{
ans+=dfs(pos-1,(z&&i==0)?0:getnews(i,s),flag&&i==end,z&&i==0);
}
if(!flag)dp[pos][s]=ans;
return ans;
}
LL solve(LL n)
{
int len=0;
while(n)
{
bit[len++]=n%10;
n/=10;
}
return dfs(len-1,0,1,1);
}
int main()
{
int T;
memset(dp,-1,sizeof(dp));
LL a,b;
scanf("%d",&T);
while(T--)
{
scanf("%lld%lld",&a,&b);
printf("%lld\n",solve(b)-solve(a-1));
}
return 0;
}
相关文章推荐
- 【HDU5898 2016 ACM ICPC Asia Regional Shenyang Online G】【数位DP】odd-even number 范围内有多少数字满足奇串长为偶数偶串长为奇数.
- 【HDU3555】数位Dp1~n之间出现特征数字个数
- 【数位DP】SPOJ 10606 BALNUM Balanced Numbers
- 【面试题】一串数字,经转换后使所有奇数在所有偶数的前面,并且奇数偶数的相对顺序不变。
- 【数据结构】输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分。
- 输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所 有偶数位于数组的后半部分。要求时间复杂度为O(n)。
- 调整数组使奇数全部都位于偶数前面。 题目: 输入一个整数数组,实现一个函数,来调整该数组中数字的顺序使得数组中所有的奇数位于数组的前半部分,所有偶数位于数组的后半部分。
- poj 3252 数位dp(dfs写法) 二进制0出现比1多的数字个数
- 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
- SPOJ10606---Balanced Numbers(三进制数位dp)
- SPOJ 10606 Balanced Numbers - 数位dp
- spoj 10606 Balanced Numbers 数位dp
- 【hdu5898】【数位DP】odd-even number 【连续奇数长度为偶数,连续的偶数的长度是奇数】
- SPOJ 10606. Balanced Numbers (数位DP,4级)
- 给出N个正整数,其中只有一个数出现了奇数次,其余的数都出现偶数次。求那个出现了奇数次的数。1<=N<=1000,N肯定是奇数。所有出现的整数都不超过1000。
- spoj 10606 BALNUM - Balanced Numbers 数位dp
- 【动态规划】【数位DP】[SPOJ10606]Balanced numbers
- 输入一个整数数组,调整数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分
- spoj10606 数位dp
- 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。