標籤:acm 數位統計
1057. Amount of DegreesTime limit: 1.0 second
Memory limit: 64 MB
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 = 24+20,
18 = 24+21,
20 = 24+22.InputThe 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).OutputOutput should contain a single integer — the amount of integers, lying between
X and
Y, being a sum of exactly
K different integer degrees of
B.Sample
Problem Source: Rybinsk State Avia Academy數位統計的第一題。看的劉聰的論文:淺談數位類統計問題http://wenku.baidu.com/view/d2414ffe04a1b0717fd5dda8.html
做完這道題,覺得數位統計真的很奇妙,不需要一個數一個數的去枚舉判斷,在判斷一個數的時候,把比它小的數全都判斷了出來,效率高。其中也有組合的運用,當高位確定後,後面幾位就隨便取就可以。題目中當B不是二進位時:
為什麼這樣做呢? 一個數可以化成題意中給的形式,其B進位數中係數中應該不是0,就是1,如果從左至右找到係數>1,那麼這個數肯定是不符合題意的,應該使其化為1,這就使得原數小了一些,為了不漏掉一些數,應使修改的這一位後面的所有位都變為1,這樣是最大的且不超過n的B進位中只包含0和1的數。這樣化完以後按照二進位做就可以了。代碼:
#include <iostream>#include <string.h>using namespace std;int X,Y,K,B;int c[40][40];void init()//組合數{ c[0][0]=1; for(int i=1;i<=31;i++) { c[i][0]=c[i-1][0]; for(int j=1;j<=i;++j) c[i][j]=c[i-1][j]+c[i-1][j-1]; }}int change(int n){ int b[40]; int len=0; while(n) { b[len++]=n%B; n/=B; } int ans=0; for(int i=len-1;i>=0;i--) { if(b[i]>1) { for(int j=i;j>=0;j--) ans+=(1<<j); break; } else ans+=(b[i]<<i); } return ans;}int cal(int x,int k){ int tot=0,ans=0; for(int i=31;i>0;i--) { if(x&(1<<i))//第i位為1(從0開始的),那麼後面還剩下i個數字,後面的第一個數字為0,從i-1個數字中任意挑k-tot個 { ++tot; if(tot>k) break; x=x^(1<<i);//1變為0 } if((1<<(i-1))<=x) ans+=c[i-1][k-tot]; } if(tot+x==k)//考慮x這個數本身 ++ans; return ans;}int main(){ init(); while(cin>>X>>Y>>K>>B) cout<<cal(change(Y),K)-cal(change(X-1),K)<<endl; return 0;}