数位dp(dfs)
1.
Amount of Degrees
Create a code to determine the amount of integers, lying in the set [X; Y] 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.
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
input | output |
---|---|
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。
输出描述:
对于每组数据输出一行,表示答案。
备注:
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
样例 2
#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; }