URAL 1057. Amount of Degrees (數位DP)
阿新 • • 發佈:2019-02-02
1057. Amount of Degrees
Time limit: 1.0 secondMemory limit: 64 MB
Create a code to determine the amount of integers, lying in the set [X;Y] and being a sum of exactlyK 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:
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 YSample
input | output |
---|---|
15 20
2
2
|
3
|
實質上:求[X,Y] 區間轉化為 B 進位制 1 的個數為K 的數的出現次數。
題解:數位DP。
注意:只有係數為1的情況,所以每位只能是0,1,至於不相同的只要是取1 的時候不不相同,至於0是不變的。
大體思路: 所求的數為互不相等的冪之和,亦即其B進製表示的各位數字都只能是0和1。 因此,我們只需討論二進位制的情況,其他進位制都可以轉化為二進位制求解。 本題區間滿足區間減法,因此可以進一步簡化問題:令count[i..j]表示[i..j]區間內合法數的個數,則 count[i..j]=count[0..j]-count[0..i-1]。 換句話說,給定n,我們只需求出從0到n有多少個符合條件的數。 步驟: 首先預處理f。 f[i,j]代表i位二進位制數中恰好有j個1的數的個數。 f[i,j]=f[i-1,j]+f[i-1,j-1] 計算count[0..n] 像前幾題一樣,一位一位列舉,只需要多記錄後面需要的1的個數即可。 if digit[i] = 1 then ans = ans + f[i,need] need就是後面需要的1的個數。 AC程式碼:#include <stdio.h>
#include <cstring>
#include <vector>
#include <algorithm>
#include <string.h>
using namespace std;
int digit[33];
typedef long long LL;
const int N = 50;
int f[N][N]; //f[i][j]表示前i箇中選 j 個 1的個數
void init()
{
f[0][0] = 1;
for(int i=1;i<33;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 solve(int x,int k,int B)
{
int len=-1;
//vector<int> v;
while(x)
{
digit[++len]=x%B;
//v.push_back(x%B);
x/=B;
}
int cnt = 0,ans = 0;
for(int i=len;i>=0;i--)
{
if(digit[i]==1) // 如果為 1,則依次求解
{
ans+=f[i][k-cnt]; //need
cnt++;
if(cnt==k)
break;
}
else if(digit[i]>1) //假如大於1的話,相當於所有的位可以為 1,所以直接求解跳出
{
ans += f[i+1][k-cnt];
break;
}
}
if(cnt==k)
ans++;
return ans;
}
int main()
{
init();
int x,y,k,B;
while(~scanf("%d%d%d%d",&x,&y,&k,&B))
{
printf("%d\n",solve(y,k,B)-solve(x-1,k,B));
}
return 0;
}