数位dp(dfs)

1.

                                        Amount of Degrees

Create a code to determine the amount of integers, lying in the set [XY] and being a sum of exactly Kdifferent integer degrees of the integer B.
Example. Let X = 15, Y = 20, K = 2, B = 2. By this example three integers are the sum of exactly two integer degrees of number 2:
17 = 2^4 + 2^0,
18 = 2^4 + 2^1,
20 = 2^4 + 2^2.

Input

The first line contains integers X and Y (1 ≤ X ≤ Y ≤ 2^31 − 1). The next two lines contain integers K and B(1 ≤ K ≤ 20; 2 ≤ B ≤ 10).

Output

Output the amount of integers, lying between X and Y, being a sum of exactly K different integer degrees of B.

Sample

inputoutput
15 20
2
2
3
 
这个是转化进制
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int l,r,k,b;
const int maxn=1e3+100; 
int a[maxn];
int f[maxn][maxn];
int dfs(int pos,int sum,int limit){
    if(pos==0){
        return sum?0:1;
    }
    if(sum<0){
        return 0;
    }
    if(!limit&&~f[pos][sum])
        return f[pos][sum];
    int up=limit?min(a[pos],1):1;
    int ans=0;
    for(int i=0;i<=up;i++){
        ans+=dfs(pos-1,sum-i,limit&&i==a[pos]); 
    } 
    if(!limit){
        f[pos][sum]=ans;
    }
    return ans;
} 
int solve(int x){
    memset(f,-1,sizeof(f));
    int cnt=0;
    while(x){
        a[++cnt]=x%b;
        x/=b;
    }    
    return dfs(cnt,k,1);
}
int main(){
    cin>>l>>r>>k>>b;
    cout<<solve(r)-solve(l-1)<<endl;
    return 0;
}

 

                                                                                          开心数

链接:https://ac.nowcoder.com/acm/contest/13545/F
来源:牛客网

对于数x(十进制),如果它的二进制数位上有一位是为0的。我们就称为是开心数。如6,二进制位110,就是开心数。

求在一个区间内[l,r]上有多少个开心数?

输入描述:

输入包含多组数据。
输入第一行T,表示数据组数。
每组数组仅有一行,包含两个正整数l,r。

输出描述:

对于每组数据输出一行,表示答案。

示例1

输入

复制
2
5 10
2015 2015

输出

复制
2
1

备注:

l, r <= 10^18, t <= 10000

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int maxx = 1e18+2;
const int mod = 100003;
const int N = 1e5+7;
vector<int> num;
// pos  pre zero
int dp[62][62][10];
int a[100];

int dfs(int pos,int sta,int pre,int limit,int lead){
    if(pos == -1){
        return (sta == 1);
    }
    if(!lead && !limit && dp[pos][sta][pre] != -1) return dp[pos][sta][pre];

    int res = 0;
    int up = limit ? a[pos] : 1;
    for(int i = 0 ; i <= up ; i ++){
        res += dfs(pos-1,sta+(!lead && (i == 0)),i,limit && (i == up),lead && (i == 0));
    }
    if(!lead && !limit)
        dp[pos][sta][pre] = res;
    return res;
}

int solve(int x){
    if(x <= 1) return 0;
    int pos = 0;
    while(x){
        a[pos] = x%2;
        x /= 2;
        pos ++;
    }
    return dfs(pos-1,0,0,1,1);
}

signed main(){
    int t;
    cin>>t;
    memset(dp,-1,sizeof(dp));
    while(t--){
        int l,r;cin>>l>>r;
        cout<<solve(r)-solve(l-1)<<endl;
    }
}

 

                                                                                                            Windy 数

原题来自:SCOI 2009

Windy 定义了一种 Windy 数:不含前导零且相邻两个数字之差至少为  的正整数被称为 Windy 数。

Windy 想知道,在  和  之间,包括  和 ,总共有多少个 Windy 数?

输入格式

一行两个数,分别为 。

输出格式

输出一个整数,表示答案。

样例 1
输入复制
1 10
输出复制
9
 
样例 2
输入复制
25 50
输出复制
20
 
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int l,r;
int a[20];
int f[100][100];
int dfs(int pos,int st,int limit,int lead){
    //cout<<pos<<" "<<st<<" "<<limit<<endl; 
    if(pos==0){
        return 1;
    }
    if(!lead&&!limit&&~f[pos][st]) return f[pos][st];
    int up=limit?a[pos]:9;
    int sum=0;
    for(int i=0;i<=up;i++){
        if(abs(st-i)<2) continue;
        if(st==11&&i==0){
            sum+=dfs(pos-1,11,limit&(i==up),lead && (i == 0));
        }
        else{
            sum+=dfs(pos-1,i,limit&(i==up),lead && (i == 0));
        }
    }
    if (!limit&&!lead) f[pos][st] = sum;
      return sum;
}
int solve(int x){
    memset(f,-1,sizeof(f));
    int cnt=0;
    while(x){
        a[++cnt]=x%10;
        x/=10;
    }    
    return dfs(cnt,11,1,1);
}
int main(){
    cin>>l>>r;
    cout<<solve(r)-solve(l-1)<<endl;
}

 

posted @ 2021-04-11 19:46  lipu123  阅读(12)  评论(0)    收藏  举报