解题思路:
求0 到 N中含有49的数字的个数
dp[i][0] 表示 长度 为 i 且不含49。
dp[i][1] 表示长度为 i 且不含49 且最高位 为9
dp[i][2] 表示长度为 i 且 含49;
从高位到低位处理
#include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <cmath> #include <vector> #include <queue> #include <stack> #include <map> #include <set> #define LL long long using namespace std; LL dp[25][3]; //预处理dp数组 void init() { dp[0][0] = 1; dp[0][1] = dp[0][2] = 0; for(int i=1;i<25;i++) { dp[i][0] = dp[i-1][0] * 10 - dp[i-1][1]; dp[i][1] = dp[i-1][0]; dp[i][2] = dp[i-1][2] * 10 + dp[i-1][1]; } } int bit[25]; LL solve(LL n) { memset(bit,0,sizeof(bit)); LL ans = 0; int len = 0; while(n) { bit[++len] = n % 10; n /= 10; } bool flag = false; for(int i=len;i>=1;i--) { ans += bit[i] * dp[i-1][2];//当前位可放置0 ~ bit[i]-1,一共是bit[i]个数字 if(flag) ans += dp[i-1][0] * bit[i];//如果前面出现49,当前位可放置bit[i]个数字 else if(bit[i] > 4) ans += dp[i-1][1];//如果前面没有49,则当前必须为4 if(bit[i+1] == 4 && bit[i] == 9) flag = true; } if(flag) ans++;//如果最后两位是49,再加一,即N本身是满足条件的数 return ans; } int main() { int T; scanf("%d", &T); init(); while(T--) { LL n; scanf("%I64d", &n); printf("%I64d\n", solve(n)); } return 0; }
原文地址:http://blog.csdn.net/moguxiaozhe/article/details/43915799