zoukankan      html  css  js  c++  java
  • SPOJ BALNUM

    题目链接:http://www.spoj.com/problems/BALNUM/en/

    Time limit: 0.123s
    Source limit: 50000B
    Memory limit: 1536MB

    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

    题意:

    问A到B之间有多少个数,有多少数符合以下条件:

      数字0~9,每个奇数出现偶数次, 每个偶数出现奇数次,当然没出现的话无所谓。

    题解:

    这题可以说是我第一道能自己想出思路来的数位DP了;

    看到这个,先开始想,数字0~9,有关出现次数,感觉可以用状压做:0~9一共十位,每位0或者1,代表这个数字出现了偶数次/奇数次……

    然后仔细看了一下,发现没法用0/1来记录,因为有一个digit有三个状态:没出现、出现偶数次、出现奇数次;

    然后有一瞬间,想到了是不是可以用三进制做,不过没仔细想下去,后来OB了一下题解,发现真可以用三进制状态压缩做。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef unsigned long long ll;
    int dig[20];
    ll dp[20][59049];
    //dp[pos][sta]:从第len位到第pos+1位各个digit出现情况为sta,剩下的第1位到第pos位任意,共有多少个数字满足题目条件.
    
    int digit[59049][10]; //digit[sta][pos]:对于三进制状态压缩sta,它的第pos位是0or1or2.
    int pow3[11]; //pow3[pos]:记录3的pos次方.
    void init()
    {
        pow3[0]=1;
        for(int i=1;i<=10;i++) pow3[i]=pow3[i-1]*3;
    
        for(int sta=0;sta<pow3[10];sta++)
            for(int pos=0;pos<=9;pos++)
            {
                digit[sta][pos]=(sta/pow3[pos])%pow3[1];
                //printf("digit[%d][%d]=%d
    ",sta,pos,digit[sta][pos]);
            }
    }
    bool check(int sta) //检查sta是不是满足题目条件
    {
        for(int i=0;i<=9;i++)
        {
            if(i%2==1 && digit[sta][i]==1) return 0;
            if(i%2==0 && digit[sta][i]==2) return 0;
        }
        return 1;
    }
    int getNewSta(int sta,int x) //更新sta
    {
        if(digit[sta][x]<=1) return sta+pow3[x];
        else return sta-pow3[x];
    }
    ll dfs(int pos,int sta,bool limit)
    {
        if(pos==0) return check(sta); //精确了到某一个数字,检查这个数字是否满足题目条件
        if(!limit && dp[pos][sta]!=-1) return dp[pos][sta];
    
        int up=limit?dig[pos]:9;
        ll ans=0;
        for(int i=0;i<=up;i++)
        {
            if(sta==0 && i==0) ans+=dfs(pos-1,0,limit && i==up); //到第pos位前面全部都是前导零,那么当前第pos位也是0的话,就不记录到sta里
            else ans+=dfs(pos-1,getNewSta(sta,i),limit && i==up); //将当前的第pos位记录到sta里
        }
    
        if(!limit) dp[pos][sta]=ans;
        return ans;
    }
    ll solve(ll x)
    {
        int len=0;
        while(x)
        {
            dig[++len]=x%10;
            x/=10;
        }
        return dfs(len,0,1);
    }
    
    int main()
    {
        init();
        memset(dp,-1,sizeof(dp));
    
        int t; ll A,B;
        scanf("%d",&t);
        while(t--)
        {
            cin>>A>>B;
            cout<<solve(B)-solve(A-1)<<endl;
        }
    }
  • 相关阅读:
    Myeclipse学习总结(5)——Myeclipse常用快捷键再学习
    Myeclipse学习总结(5)——Myeclipse常用快捷键再学习
    Java基础学习总结(37)——Java23中设计模式(Design Patterns)详解
    Java基础学习总结(37)——Java23中设计模式(Design Patterns)详解
    Java基础学习总结(37)——Java23中设计模式(Design Patterns)详解
    Git学习总结(4)——我的Git忽略文件
    Git学习总结(4)——我的Git忽略文件
    Git学习总结(4)——我的Git忽略文件
    《跟唐老师学习云网络》 -第5篇 Ping喂报文
    深入比特币原理(五)——高级交易与脚本
  • 原文地址:https://www.cnblogs.com/dilthey/p/8551498.html
Copyright © 2011-2022 走看看