NKOJ5059 幂和的数量 数位DP
题面:写一个程序来计算区间[X,Y]内满足如下条件的整数个数:它恰好等于K个互不相等的B的整数幂之和。
解法:设f[i][j]表示长度为i的二进制数中,数字1出现了j次的数的个数。转化为求Cnt[n]:在[1…n]区间的B进制表示中,只由数字0和1构成,且数字1出现次数为k的数字个数。
前面讨论的是二进制(B==2)的情况,怎么处理非二进制的情况呢?
找到n的左起第一位非0、1 的数位,将它变为1,并将右面所有数位设为1。
将得到的B进制表示视为二进制,然后按照前面的讨论进行询问即可。
#include <bits/stdc++.h> using namespace std; int f[105][105]; int x, y, k, b; int getcnt(int x, int k) { int tot = 0, ans = 0; for (int i = 31; i; i--) { if (x & (1 << i)) { tot++; if (tot > k) break; x ^= (1 << i); } if ((1 << (i - 1)) <= x) ans += f[i - 1][k - tot]; } if (tot + x == k) ans++; return ans; } int change(int x) { int p = 1, tot = 0, ans = 0; while (x >= p * b) p *= b, tot++; while (p && x / p <= 1) ans += x / p * (1 << tot--), x %= p, p /= b; ans += (1 << (tot + 1)) - 1; return ans; } int main() { scanf("%d%d%d%d", &x, &y, &k, &b); f[0][0] = 1; for (int i = 1; i <= 31; i++) { f[i][0] = f[i - 1][0]; for (int j = 1; j <= i; j++) { f[i][j] = f[i - 1][j] + f[i - 1][j - 1]; } } printf("%d", getcnt(change(y), k) - getcnt(change(x - 1), k)); }

浙公网安备 33010602011771号