SPOJ10606 BALNUM - Balanced Numbers(数位DP+状压)

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.

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

题意:求l-r之间13579是偶数个,24680是奇数个的数的个数

题解:状压压一下每一位是奇是偶,1表示奇,2表示偶,0表示没取dp[pos][sta]表示第pos位之前sta的数有几个最基础的数位DP写法记得去一下前导零

代码如下:
#include<bits/stdc++.h>
using namespace std;

int n;
long long l,r;
long long dp[23][60000][2],a[23],b3[12];

int gg(int x,int pos)
{
    return (x%b3[pos+1])/b3[pos];
}

inline int check(int sta)
{
    for(int i=1;i<=9;i+=2)
    {
        if(gg(sta,i)==1) return 0;
    }
    for(int i=0;i<=8;i+=2)
    {
        if(gg(sta,i)==2) return 0;
    }
    return 1;
}

long long dfs(int pos,int sta,int lim,int lim2)
{
    if(pos<=0) return check(sta);
    if(!lim&&dp[pos][sta][lim2]!=-1) return dp[pos][sta][lim2];
    int up=lim?a[pos]:9;
    long long res=0;
    int nextsta;
    for(int i=0;i<=up;i++)
    {
        if(!lim2&&i==0)
        {
            res+=dfs(pos-1,sta,lim&&i==a[pos],lim2);
        }
        else
        {
            if(gg(sta,i)!=2) nextsta=sta+b3[i];
            else nextsta=sta-b3[i];
            res+=dfs(pos-1,nextsta,lim&&i==a[pos],lim2|1);
        }
    }
    if(!lim) dp[pos][sta][lim2]=res;
    return res;
}

long long get(long long x)
{
    memset(dp,-1,sizeof(dp));
    int cnt=0;
    while(x)
    {
        a[++cnt]=x%10;
        x/=10;
    }
    return dfs(cnt,0,1,0);
}

int main()
{
    b3[0]=1;
    for(int i=1;i<=11;i++) b3[i]=b3[i-1]*3;
    scanf("%d",&n);
    while(n--)
    {
        scanf("%lld%lld",&l,&r);
        printf("%lld\n",get(r)-get(l-1));
    }
}


原文地址:https://www.cnblogs.com/stxy-ferryman/p/9726319.html

时间: 2024-12-16 23:38:53

SPOJ10606 BALNUM - Balanced Numbers(数位DP+状压)的相关文章

SPOJ BALNUM Balanced Numbers(数位dp)

Balanced Numbers Time Limit:123MS     Memory Limit:1572864KB     64bit IO Format:%lld & %llu Submit Status Practice SPOJ BALNUM Description Balanced numbers have been used by mathematicians for centuries. A positive integer is considered a balanced n

Balanced Numbers数位dp

三进制搞下, 0  表示没出现过,  第i位为1 表示 i出现了奇数次,  2表示i 出现了偶数次. #include <cstdio> #include <cstring> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #includ

HDU 4352 XHXJ&#39;s LIS 数位DP + 状压

由LIS的nlogn解法 可以得出最后统计数组中数的个数即为LIS的长度 这样就可以状压了 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <c

HDU.4352.XHXJ&#39;s LIS(数位DP 状压 LIS)

题目链接 数位DP. 至于怎么求LIS,因为只有10个数,所以可以参照O(nlogn)求LIS的方法,状压记录状态. 每次加一个数和求LIS一样更新状态.最后状态中1的个数就是LIS的长度. //93MS 3004K #include <cstdio> #include <cctype> #include <cstring> #include <algorithm> #define gc() getchar() typedef long long LL; c

spoj Balanced Numbers(数位dp)

一个数字是Balanced Numbers,当且仅当组成这个数字的数,奇数出现偶数次,偶数出现奇数次 一下子就相到了三进制状压,数组开小了,一直wa,都不报re, 使用记忆化搜索,dp[i][s] 表示长度为i,状态为s,时,满足条件的balance number的个数 #include <stdio.h> #include <string.h> #include <stdlib.h> #include <algorithm> #include <io

CCF 201312-4 有趣的数 (数位DP, 状压DP, 组合数学+暴力枚举, 推公式, 矩阵快速幂)

问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次. 2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前. 3. 最高位数字不为0. 因此,符合我们定义的最小的有趣的数是2013.除此以外,4位的有趣的数还有两个:2031和2301. 请计算恰好有n位的有趣的数的个数.由于答案可能非常大,只需要输出答案除以1000000007的余数. 输入格式 输入只有一行,包括恰好一个正整数n (4 ≤ n ≤ 1000). 输

lightoj 1021 - Painful Bases(数位dp+状压)

题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1021 题解:简单的数位dp由于总共就只有16个存储一下状态就行了. #include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; typedef long long ll; ll dp[1 << 17

spoj 10606 Balanced Numbers 数位dp

题目链接 一个数称为平衡数, 满足他各个数位里面的数, 奇数出现偶数次, 偶数出现奇数次, 求一个范围内的平衡数个数. 用三进制压缩, 一个数没有出现用0表示, 出现奇数次用1表示, 出现偶数次用2表示, 这样只需要开一个20*60000的数组. 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define pb(x) push_back(x) 4 #define ll long long 5 #define mk(x, y) make_

SPOJ BALNUM Balanced Numbers 状压+数位DP

一开始想了一个用二进制状压的方法,发现空间需要的太大,光光memset都要超时 = = 其实不用每次都memset 也可以用三进制,一开始直接打表出所有的状态转移就好 #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream&g