当年大神的文章 《浅谈数位统计问题》
对于没什么文化(x 没有充分时间或懒得看那么多理论 应付个水考试的我
eg:62问题
1 #include <iostream> 2 #include <string> 3 #include <string.h> 4 #include<fstream> 5 #include <algorithm> 6 using namespace std; 7 int dp[10][10];//dp[i][j],表示开头是j的i位数满足条件的有多少个 8 //注意计算得到的i位数并不是数学意义上的i位数 最高位可以为0 9 void init() 10 { 11 memset(dp, 0, sizeof(dp));//初始化数组all 0 12 dp[0][0] = 1; 13 for (int i = 1; i <= 7; i++) 14 { 15 for (int j = 0; j<10; j++)//枚举第i位可能出现的数 16 { 17 for (int k = 0; k<10; k++)//枚举第i-1位可能出现的数 18 { 19 if (j != 4 && !(j == 6 && k == 2)) 20 dp[i][j] += dp[i - 1][k];//高位每次出现的数字 对应数的个数 21 //为低位每次出现数字对应数的个数之和 22 } 23 } 24 } 25 } 26 int solve(int n) 27 { 28 init(); 29 int digit[10]; 30 int len = 0; 31 while (n>0)//把我们要计算的数一位一位地存到digit数组中 32 { 33 digit[++len] = n % 10; 34 n /= 10; 35 } 36 digit[len + 1] = 0;//最高位补零(只要不是6),因为下面从最高位开始参考前一位是否和现在构成62 37 int ans = 0;//初始化符合个数 38 for (int i = len; i; i--)//从最高位开始 39 { 40 for (int j = 0; j<digit[i]; j++)//从小到大遍历,有上界 41 { 42 if (j != 4 && !(digit[i + 1] == 6 && j == 2))//如果符合要求(没有4,62) 43 ans += dp[i][j];//就加以j开头的符合要求的i位数 44 } 45 if (digit[i] == 4 || (digit[i] == 2 && digit[i + 1] == 6))//如果不符合要求 结束本层循环(也就是直接退出了 46 break; 47 } 48 return ans; 49 } 50 int main() 51 { 52 int l, r; 53 while (cin >> l >> r) 54 { 55 if (l + r == 0) 56 break; 57 else 58 cout << solve(r + 1) - solve(l) << endl; 59 } 60 return 0; 61 62 }