Balanced Numbers(数位+状压)

题意:求给定区间,一个数的数位上每个奇数出现偶数次,每个偶数出现奇数次,这样数的个数

分析:先考虑状态,但总是想不全,所以要把状态压缩一下,用三进制,0 该数不放  1 放了奇数次 2放了偶数次

dp[i][j] 长度为i 状态是j的数字个数,需要前导0判断,前导0不能计入偶数出现的次数。

#include <map>
#include <set>
#include <list>
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <vector>
#include <string>
#include <cctype>
#include <complex>
#include <cassert>
#include <utility>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef pair<int,int> PII;
typedef long long ll;
#define lson l,m,rt<<1
#define pi acos(-1.0)
#define rson m+1,r,rt<<11
#define All 1,N,1
#define read freopen("in.txt", "r", stdin)
const ll  INFll = 0x3f3f3f3f3f3f3f3fLL;
const int INF= 0x7ffffff;
const int mod =  1000000007;
ll dp[25][100000],a,b;
int bit[25],cas[15];//化三进制
void get(int x)
{
    for(int i=0; i<10; ++i)
    {
        cas[i]=x%3;
        x/=3;
    }
}//状态改变
int change(int x,int b)
{
    get(x);
    if(cas[b]==0)
        cas[b]=1;
    else if(cas[b]==1)
        cas[b]=2;
    else cas[b]=1;
    int s=0,tmp=1;
    for(int i=0; i<10; ++i)
    {
        s+=cas[i]*tmp;
        tmp*=3;
    }
    return s;
}//判断符合条件
int judge(int s)
{
    get(s);
    for(int i=0; i<10; ++i)
    {
        if(i%2&&cas[i]==1)return 0;
        if(i%2==0&&cas[i]==2)return 0;
    }
    return 1;
}
ll dfs(int i,int j,int f,int e)
{
    if(i==0)return judge(j);
    if(!e&&dp[i][j]!=-1)return dp[i][j];
    int u=e?bit[i]:9;
    ll num=0;
    for(int v=0; v<=u; ++v)
    {
        if(f&&v==0)
            num+=dfs(i-1,0,1,e&&(v==u));
        else
        {
            num+=dfs(i-1,change(j,v),0,e&&(v==u));
        }
    }
    if(!e)dp[i][j]=num;
    return num;
}
ll solve(ll x)
{
    int len=0;
    while(x)
    {
        bit[++len]=x%10;
        x/=10;
    }
    return dfs(len,0,1,1);
}
int main()
{
    int t;
    scanf("%d",&t);
    memset(dp,-1,sizeof(dp));
    while(t--)
    {
        scanf("%I64d%I64d",&a,&b);
        printf("%I64d\n",solve(b)-solve(a-1));
    }
    return 0;
}
时间: 2024-08-15 23:54:14

Balanced Numbers(数位+状压)的相关文章

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

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 numb

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

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 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_

[HDOJ5676]ztr loves lucky numbers(状压枚举,打表,二分)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5676 题意:输入一个正整数n(n <=10^18),求不小于n的只有4和7组成的数,且4和7数量相同 枚举2~18位偶数位的4.7的组合,01分别代表4或7.存下来后排序,二分查询. trick就是LL存不下20位的数,但是n<=10^18,那么只要特判大于777777777444444444的数都输出44444444447777777777就行了. 1 #include <bits/std

【Codeforces】CF 165 E Compatible Numbers(状压dp)

题目 传送门:QWQ 分析 很难想到方向,但有方向了就很easy了. 我们如何减少不必要的计算? 如果我们知道了$ 100111 $的相容的数,$ 100101 $的相容数和他是完全一样的. 我们就靠着这个思想写一下就行了. 注意位运算优先级. 代码 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int maxn=1<<22, INF=(1<<22)-1; 4 5 int dp[maxn], a[ma

SPOJ BALNUM Balanced Numbers 状压+数位DP

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

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

1021 - Painful Bases PDF (English) Statistics ForumTime Limit: 2 second(s) Memory Limit: 32 MBAs you know that sometimes base conversion is a painful task. But still there are interesting facts in bases. For convenience let's assume that we are deali