[数位dp] spoj 10606 Balanced Numbers

题意:

对于一个数的每个位上的数。

对于每个奇数,如果出现必须出现偶数次。

对于每个偶数,如果出现必须出现奇数次。

思路:

用三进制存储每个数出现的状态,0没出现,1出现奇数次,2出现偶数次。

然后其他和普通数位dp就一样了。

代码:

#include"cstdlib"
#include"cstdio"
#include"cstring"
#include"cmath"
#include"queue"
#include"algorithm"
#include"iostream"
using namespace std;
//2014年9月25日10:03:08
long long dp[22][180000];
int num[22];
int ok(int x)
{
    int v[50],cnt=0;
    while(x)
    {
        v[cnt++]=x%3;
        x/=3;
    }
    for(int i=0;i<cnt;i++)
    {
        if(!v[i]) continue;
        if(i%2==0&&v[i]!=1) return 0;
        if(i%2!=0&&v[i]!=2) return 0;
    }
    return 1;
}
int js(int n,int x)
{
    int v[50],cnt=0,tep=0;
    memset(v,0,sizeof(v));
    while(n)
    {
        v[cnt++]=n%3;
        n/=3;
    }
    if(v[x]<2) v[x]++;
    else v[x]=1;
    for(int i=9;i>=0;i--) tep=tep*3+v[i];
    return tep;
}
long long dfs(int site,int n,int zero,int f)
{
    if(site==0)
    {
        if(zero) return 0;
        return ok(n);
    }
    if(!f&&!zero&&~dp[site][n]) return dp[site][n];
    int len=f?num[site]:9;
    long long ans=0;
    for(int i=0; i<=len; i++)
    {
        if(zero)
        {
            if(i==0) ans+=dfs(site-1,n,zero&&i==0,f&&i==len);
            else ans+=dfs(site-1,js(n,i),zero&&i==0,f&&i==len);
        }
        else ans+=dfs(site-1,js(n,i),zero&&i==0,f&&i==len);
    }
    if(!f&&!zero) dp[site][n]=ans;
    return ans;
}
long long solve(long long x)
{
    int cnt=0;
    while(x)
    {
        num[++cnt]=x%10;
        x/=10;
    }
    return dfs(cnt,0,1,1);
}
int main()
{
    int t;
    cin>>t;
    memset(dp,-1,sizeof(dp));
    while(t--)
    {
        long long x,y;
        scanf("%lld%lld",&x,&y);
        printf("%lld\n",solve(y)-solve(x-1));
    }
    return 0;
}
//2014年9月25日10:39:37
时间: 2024-08-29 11:20:23

[数位dp] spoj 10606 Balanced Numbers的相关文章

[数位dp] spoj 10738 Ra-One Numbers

题意:给定x.y,为[x,y]之间有多少个数的偶数位和减去奇数位和等于一. 个位是第一位. 例子: 10=1-0=1 所以10是这样的数 思路:数位dp[i][sum][ok] i位和为sum 是否含有前导0. 然后就是因为有负数 所以根据范围把0设置为100 然后最后和等于101则为所求的数. 代码: [cpp] view plaincopyprint? #include"cstdlib" #include"cstdio" #include"cstrin

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

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

SPOJ BALNUM Balanced Numbers(数位dp,状态压缩)

BALNUM - Balanced Numbers no tags 题目链接 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)   

SPOJ - BALNUM - Balanced Numbers(数位DP)

链接: https://vjudge.net/problem/SPOJ-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)

找规律/数位DP HDOJ 4722 Good Numbers

题目传送门 1 /* 2 找规律/数位DP:我做的时候差一点做出来了,只是不知道最后的 is_one () 3 http://www.cnblogs.com/crazyapple/p/3315436.html 4 数位DP:http://blog.csdn.net/cyendra/article/details/11606209 5 */ 6 #include <cstdio> 7 #include <iostream> 8 #include <algorithm> 9

SPOJ BALNUM Balanced Numbers 平衡数(数位DP,状压)

题意: 平衡树定义为“一个整数的某个数位若是奇数,则该奇数必定出现偶数次:偶数位则必须出现奇数次”,比如 222,数位为偶数2,共出现3次,是奇数次,所以合法.给一个区间[L,R],问有多少个平衡数? 思路: 这题比较好解决,只有前导零问题需要解决.如果枚举到011,那么其前导零(偶数)出现了1次而已,而此数11却是平衡数,所以不允许前导零的出现! 由于dfs时必定会枚举到前导零,否则位数较少的那些统计不到.状态需要3维or2维也行,3维的比较容易处理,用一维表示数位出现次数,另一维表示数位是否

数位DP CF 55D Beautiful numbers

题目链接 题意:定义"beautiful number"为一个数n能整除所有数位上非0的数字 分析:即n是数位所有数字的最小公倍数的倍数.LCM(1到9)=2520.n满足是2520的约数的倍数.dp[len][val][lcm]一维为数的位数,一维为%2520的值(保存原数不可能,也没必要,2520是可行的最小公倍数最大的一个),一维为当前数位的lcm,判断满足的条件是val%lcm==0.这题离散化2520的约数,否则空间开不下. #include <bits/stdc++.