[ACM] ural 1057 Amount of degrees (digital statistics), ural1057
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 exactlyKDifferent integer degreesB.Example.LetX= 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 integersXAndY, Separated with a space (1 ≤X≤Y≤ 231 −1). The next two lines contain integersKAndB(1 ≤K≤ 20; 2 ≤B≤ 10). OutputOutput shoshould contain a single integer-the amount of integers, lyingXAndY, Being a sum of exactlyKDifferent integer degreesB. Sample
Problem Source:Rybinsk State Avia Emy digital statistics first. Liu Cong's thesis: Talking about the http://wenku.baidu.com/view/d2414ffe04a1b0717fd5dda8.html of digital statistics
After finishing this question, I think the digital statistics are really amazing. I don't need to enumerate and judge a number. When I judge a number, I will judge all the numbers smaller than it, high efficiency. There is also a combination of applications, when the high level is determined, the next few digits can be taken as needed. When B is not binary in the question:
Why? A number can be converted into the form given in the question. The coefficient in the B-base number should be either 0 or 1. If the coefficient> 1 is found from left to right, this number must not match the meaning of the question. It should be converted to 1, which makes the original number smaller. In order not to miss some numbers, all the bits after this modified bit should be changed to 1, which is the largest and contains only the numbers of 0 and 1 in the B-base system with no more than n. In this way, you can do it in binary format. Code:
# Include <iostream> # include <string. h> using namespace std; int X, Y, K, B; int c [40] [40]; void init () // number of combinations {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 )) // the I-th digit is 1 (starting from 0), so there are still I numbers behind it, and the first number behind it is 0, pick k-tot {+ tot from any number in the I-1; if (tot> k) break; x = x ^ (1 <I ); // 1 to 0} if (1 <(I-1) <= x) ans + = c [I-1] [k-tot];} if (tot + x = k) // consider the number x itself + + 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 ;}