您的位置:首页 > 其它

URAL 1057 - Amount of Degrees (入门数位DP)

2014-08-10 10:30 459 查看
Amount of Degrees

Time Limit: 1000MSMemory Limit: 65536KB64bit IO Format: %I64d & %I64u
[Submit]
[Go Back] [Status]

Description

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 = 2 4+2 0,

18 = 2 4+2 1,

20 = 2 4+2 2.

Input

The first line of input contains integers X and Y, separated with a space (1 ≤ X ≤ Y ≤ 2 31−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 ofB.

Sample Input

inputoutput
15 20
2
2

3

Source

Problem Source: Rybinsk State Avia Academy

[Submit]
[Go Back] [Status]

详见刘聪论文 《浅谈数位类统计问题》

后的问题就是如何处理非二进制。对于询问 n,我们需要求出不超过 n 的最大 B 进制

表示只含 0、1 的数:找到 n 的左起第一位非 0、1 的数位,将它变为 1,并将右面所有数位

设为 1。将得到的 B 进制表示视为二进制进行询问即可。

如change函数

#include <cstdio>
#include <iostream>
#include <vector>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <queue>
#include <set>

using namespace std;

//#define WIN
#ifdef WIN
typedef __int64 LL;
#define iform "%I64d"
#define oform "%I64d\n"
#define oform1 "%I64d"
#else
typedef long long LL;
#define iform "%lld"
#define oform "%lld\n"
#define oform1 "%lld"
#endif

#define S64I(a) scanf(iform, &(a))
#define P64I(a) printf(oform, (a))
#define P64I1(a) printf(oform1, (a))
#define REP(i, n) for(int (i)=0; (i)<n; (i)++)
#define REP1(i, n) for(int (i)=1; (i)<=(n); (i)++)
#define FOR(i, s, t) for(int (i)=(s); (i)<=(t); (i)++)

const int INF = 0x3f3f3f3f;
const double eps = 10e-9;
const double PI = (4.0*atan(1.0));

int f[32][32];

void init() {
f[0][0] = 1;
for(int i=1; i<32; 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];
}
}
}

int cal(int x, int k) {
int ans = 0, tot = 0;
for(int i=31; i>0; i--) {
if(x&(1<<i)) {
x = x ^ (1<<i);
tot++;
if(tot > k) break;
}
if((1<<(i-1)) <= x) {
ans += f[i-1][k-tot];
}
}
if(tot+x == k) ans++;
return ans;
}

int change(int x, int b) {
int ans = 0;
int a[32], p=0;
while(x) {
a[p++] = x%b;
x /= b;
}
int i;
for(i=p-1; i>=0; i--) {
if(a[i] == 1) ans |= (1<<i);
else if(a[i] > 1) break;
}
if(i>=0) ans = ans | ((1<<(i+1))-1);
return ans;
}

int main() {
int L, R, K, B;

init();
scanf("%d%d%d%d", &L, &R, &K, &B);
R = change(R, B);
L = change(L-1, B);
int ans = cal(R, K) - cal(L, K);
printf("%d\n", ans);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: