1. 程式人生 > >LOJ10163 Amount of Degrees

LOJ10163 Amount of Degrees

題目描述

求給定區間 [X,Y] 中滿足下列條件的整數個數:這個數恰好等於 KK 個互不相等的 BB 的整數次冪之和。例如,設 X=15,Y=20,K=2,B=2,則有且僅有下列三個數滿足題意

輸入格式

第一行包含兩個整數 X 和 Y,接下來兩行包含整數 K 和 B。

輸出格式

只包含一個整數,表示滿足條件的數的個數。

樣例

樣例輸入

15 20
2
2

樣例輸出

3

資料範圍與提示

對於全部資料,1XY2^311,1K20,2B10。

______________________________________________________________________________________________

數位動歸

一類區間統計問題,區間較大,無法用暴力求解或組合數學求解。

常見為求區間內滿足某類條件的X進位制數的個數。條件往往與數位有關。

此題:

首先,區間具有相減的性質。count[i...j]=count[ 0...j ] - count[ 0...i-1 ]。

這樣問題就變成了0到i的x進位制數有多少個滿足條件。

因為是互不相等的k進位制數,所以,轉成k進位制後,每個位上要麼是0要麼是1。

這樣f[i][j]表示長度I的2進位制數,有j個1的種類

f[i][j]=f[i-1][j]+f[i-1][j-1]

______________________________________________________________________________________________

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 int x,y,k,b;
 4 int wei[32];
 5 int f[32][32];
 6 void prech(int &x,int b)
 7 {
 8     int js=0;
 9     while(x>0)
10     {
11         wei[++js]=x%b;
12         x/=b;
13     }
14     while(js>0)
15     {
16         if(wei[js]==1)x^=1<<(js-1);
17         else if(wei[js]>1)
18         {
19             for(int i=js;i>0;--i)x^=1<<(i-1);
20             break;
21         }
22         --js;
23     }    
24 }
25 void dp()
26 {
27     f[0][0]=1;
28     for(int i=1;i<=31;++i)
29     {
30         f[i][0]=f[i-1][0];
31         for(int j=1;j<=i;++j)f[i][j]=f[i-1][j]+f[i-1][j-1];
32     }
33 }
34 int work(int x,int k)
35 {
36     int js=0,ans=0;
37     for(int i=31;i>0;--i)
38     {
39         if(x&(1<<i))
40         {
41             ++js;
42             if(js>k)break;
43             x=x^(1<<i);
44         }
45         if((1<<(i-1))&x)ans+=f[i-1][k-js];
46     }
47     if(js+x==k)ans++;
48     return ans;
49 }
50 int main()
51 {
52     scanf("%d%d%d%d",&x,&y,&k,&b);
53     x--;
54     prech(x,b);prech(y,b);
55     dp();
56     cout<<work(y,k)-work(x,k);
57     return 0;
58 }
View Code