寒假集训日志——DP
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了寒假集训日志——DP相关的知识,希望对你有一定的参考价值。
(一)数位DP
1057. Amount of Degrees
Time limit: 1.0 second
Memory limit: 64 MB
Memory limit: 64 MB
Create a code to determine the amount of integers, lying in the set [X;Y] and being a sum of exactly K different integer degrees of B.
Example. Let X=15, Y=20, K=2, B=2. By this example 3 numbers are the sum of exactly two integer degrees of number 2:
17 = 24+20,
18 = 24+21,
20 = 24+22.
18 = 24+21,
20 = 24+22.
Input
The first line of input contains integers X and Y, separated with a space (1 ≤ X ≤ Y ≤ 231−1). The next two lines contain integers K and B (1 ≤ K ≤ 20;
2 ≤ B ≤ 10).
Output
Output should contain a single integer — 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 |
一道据说比较经典的题目,基本弄懂,ans++ 那里实在没搞懂,不过也没那么多时间给我犹豫。。
主要借助一个状态转移方程 f[i][j] = f[i-1][j-1] + f[i-1][j]
f[i][j] 表示二进制中前i位中有j个1的个数,其他进制的数在转换过来之后都可一借用f[i][j]来解决。可以借助这个图理解一下这个方程。
不过ans++那里实在每看懂。
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<iomanip> #include<fstream> #include<vector> typedef long long LL; using namespace std; const int maxN = 50; int f[maxN][maxN]; void getMap (){ f[0][ 0] = 1; for( int i = 1 ; i< maxN ;++i){ f[i][0] = 1; for( int j= 1 ; j<=i ;++j) f[i][j] = f[i-1][j] + f[i-1][j-1] ; } } int solve ( int x, int k , int c) { vector< int > arr; while( x) { arr.push_back ( x% c); x /= c; } int ans = 0, cnt = 0 ; for( int i = arr.size() -1 ; i>= 0 ; --i){ if( arr[i] == 1){ ans += f[i][ k - cnt]; cnt++ ; if( cnt == k ) break; } else if( arr[i] > 1){ ans += f[i+1][k - cnt]; break; } } if( cnt == k ) ans ++; return ans ; } int main() { for( int i = 0 ; i< maxN ; ++i) for( int j = 0 ; j< maxN; ++j) f[i][j] = 0 ; int x, y ; int k, b; getMap(); cin>>x>>y>>k>>b; cout<<solve(y,k,b) - solve(x-1 , k , b)<<endl; return 0; }
(二)树形DP
以上是关于寒假集训日志——DP的主要内容,如果未能解决你的问题,请参考以下文章