數位dp and SDNUOJ1248陸歷川玩數位

數位dp就是要統計一個區間[l, r]內滿足給定條件數的個數

控制上界,往下枚舉

SDNUOJ1248陸歷川玩數位

Description

A number X have n digits(A1A2A3......An)

F(x) = A1*2n-1 + A2*2n-1 .....+An-1*21 + An *20

Now, give you two number A, B

You need to calculate how many number's F(x) is no more than F(A) between 0 to B

Input

T(0 < T<= 10000) T is TestCase

A, B (0 <= A, B <= 1000000000)

Output

Answer

Sample Input

11 1

Sample Output

Case #1: 2
#include <cstdio>
#include <map>
#include <queue>
#include <stack>
#include <cmath>
#include <vector>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

#define PI         acos(-1)
#define inf        0x3f3f3f3f
#define EPS        1e-6
#define mem(a, b)  memset(a, b, sizeof(a))
#define ll long long
#define mian main
#define N 10010

int a[20];//存放分開的數位
int dp[20][N];//dp[i][j]表示i位值<=j 的總數

ll f(ll x)//計算F(x)
{
    int ans = 0;
    int cs = 1;
    while(x)
    {
        int tmp = x%10;
        x /= 10;
        ans += tmp * cs;
        cs *= 2;
    }
    return ans;
}

int dfs(int pos, int sum, bool lim/*數位上界變量*/)
{
    /*lim的作用,比如界限爲521,搜到百位的時候枚舉0~5,枚舉4時可以有499枚舉到5的時候599>521了所以用lim*/
    if(sum < 0)return 0;
    if(pos == -1 && sum >= 0) return 1;//到了數位的最後一位並且這一位合法
    if(!lim && dp[pos][sum] != -1)return dp[pos][sum];
    int up = lim ? a[pos] : 9;//判斷枚舉上界(達到上界是a[pos]其他時候是9)
    int ans = 0;
    for(int i = 0; i <= up; i++)//枚舉這一位可能的數字
    {
        ans += dfs(pos - 1, sum - i * (1<<pos), lim && i == a[pos]);//遞歸,狀態轉移
    }
    if(!lim) dp[pos][sum] = ans;
    return ans;
}

ll solve(int x, int y)//分出數位來
{
    int pos = 0;
    while(x)
    {
        a[pos++] = x % 10;
        x /= 10;
    }
    return dfs(pos - 1, y, 1);//從最高位開始枚舉
}

int main()
{
    int t;
    int no = 0;
    ll a, b;
    cin>>t;
    mem(dp, -1);
    while(t--)
    {
        //mem(a, 0);
        no++;
        cin>>a>>b;
        //cout<<f(a)<<endl;
        int tmp = f(a);
        cout<<"Case #"<<no<<':'<<' '<<solve(b, tmp)<<endl;
    }
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章