URAL - 1057 Amount of Degrees 数位DP

在这里插入图片描述
思路

  • 对于一个数 n, 我们求他的 0 - n 的满足要求的方案数, 对于区间[l, r] = sum[r] - sum[l - 1]
  • 我们先预处理组合数, 存下对应的值
  • 我们这时取出n的每一位的值, 我们去判断一下这位的树, 如果这一位不是0, 我们直接加上这一位是0的情况, 就是这以为不选1, 前面选了last个1, 后面再选k - last个1, 就是f[i], k - last], 对于这一位大于1这种情况, 后面就可以随便选, 这一位选上1, 这样最后组成的数一定是小于n的, 对于这位是1的情况, 我们就只有选0或者选1, 0已经前面加上了, 所以就只需要处理1这种情况,但是由于1这种情况, 后面还需要讨论, 不能乱取, 所以这不符合组合数, 我们直接last++就行

代码

#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>

using namespace std;

const int N  = 35;

int f[N][N];
int x, y, k, b;

void init()
{
	for(int i = 0; i <= 34; i++)
	{
		f[i][0] = 1;
		for(int j = 1; j <= i; j++)
			f[i][j] = f[i - 1][j - 1] + f[i - 1][j];	
	}
}

int dfs(int x)
{
    if(!x) return 0;
	vector<int> num;
	while(x) num.push_back(x % b), x /= b;
	int ans = 0;
	int last = 0;
	for(int i = num.size() - 1; i >= 0; i--)
	{
		int n = num[i];
		if(n)
		{
			ans += f[i][k - last];
			if(n > 1) // 这位就随便取 
			{
				if(k - last - 1 >= 0)
					ans += f[i][k - last - 1];
				break;
			}
			else
			{
				last++;
				if(last > k)
					break;
			}
		}
		if(!i && k == last)//特判一下最后的一种情况
			ans++;
	}
	return ans;
}

int main()
{
	cin >> x >> y >> k >> b;
	init();
	int ans = dfs(y) - dfs(x - 1);
	cout << ans << endl;
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章