题意:中文题。
析:暴力先从1到1000000,然后输出就好了。
代码如下:
#include <iostream> #include <cstdio> #include <cstring> #include <map> #include <string> #include <queue> using namespace std; const int maxn = 1000000 + 10; int a[10], d[maxn]; bool judge(int n){ int j = 0; while(n){ a[j] = n % 10; n /= 10; if(4 == a[j++]) return false; } for(int i = 0; i < j; ++i) if(4 == a[i]) return false; else if(i && 2 == a[i-1] && 6 == a[i]) return false; return true; } int main(){ int n, m; for(int i = 1; i < 1000000; ++i) d[i] = judge(i) ? d[i-1] + 1 : d[i-1]; while(scanf("%d %d", &m, &n)){ if(!m && !n) break; printf("%d ", d[n]-d[m-1]); } return 0; }
也可以用数位DP来做
代码如下:
#include <iostream> #include <cstdio> #include <algorithm> #include <queue> #include <vector> #include <cstring> #include <map> #include <cctype> #include <cmath> using namespace std; typedef long long LL; const int maxn = 30; int d[10][3], a[25]; //d[i][j] 表示数字的位数,j代表状态 //d[i][0] 表示不存在不吉利的数字 //d[i][1] 表示不存在吉利数字,且最高位是2 //d[i][2] 表示存在不吉利数字 void init(){ memset(d, 0, sizeof(d)); d[0][0] = 1; for(int i = 1; i < 8; ++i){ d[i][0] = d[i-1][0] * 9 - d[i-1][1];//最高位不含有4的9个数字,而且因为当放第i位放6的时候, //i-1不能放2所以要减去一下i-1位不存在不吉利数字切最高位为2 的情况 d[i][1] = d[i-1][0];//最高位放了2其他位只要不是不吉利数字就可以 d[i][2] = d[i-1][2] * 10 + d[i-1][1] + d[i-1][0];//i位的含有不吉利数字的个数是i-1位的含有不吉利数字的×10, //因为只要后面含有不吉利数字前面不管是什么都可以所以前面×10,另外如果最高位放一个4然后后面的全部不是不吉利数字就行, //还可以是最高位放上一个6然后,倒数第二位放上2就可以的不是不吉利就行 } } int solve(int n){ int t = n; int len = 0; while(n){ a[++len] = n % 10; n /= 10; } a[len+1] = 0; int ans = 0; bool ok = false; for(int i = len; i > 0; --i){ ans += d[i-1][2] * a[i];//后面的i-1是不吉利数字之后前面就可以填上任意的 if(ok) ans += d[i-1][0] * a[i]; if(!ok && a[i] > 4) ans += d[i-1][0];//如果a[i]>4那么就可以在i位上放上一个4 if(!ok && a[i+1] == 6 && a[i] > 2) ans += d[i][1];//后一位为6,此位大于2 if(!ok && a[i] > 6) ans += d[i-1][1];//如果a[i]>6那么就可以在i位上放上一个2 if((a[i] == 2 && a[i+1] == 6) || a[i] == 4) ok = true;//标记为不吉利 } return t - ans; } int main(){ init(); int n, m; while(~scanf("%d %d", &n, &m)){ if(!m && !n) break; printf("%d ", solve(m+1) - solve(n)); //因为solve函数中并没有考虑n是不是不幸数的情况,所以r+1只算了1~r,而l只算了1~l-1,这两者相减才是正确答案 } return 0; }
#pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <string> #include <cstdlib> #include <cmath> #include <iostream> #include <cstring> #include <set> #include <queue> #include <algorithm> #include <vector> #include <map> #include <cctype> #include <cmath> #include <stack> #define freopenr freopen("in.txt", "r", stdin) #define freopenw freopen("out.txt", "w", stdout) using namespace std; typedef long long LL; typedef pair<int, int> P; const int INF = 0x3f3f3f3f; const double inf = 0x3f3f3f3f3f3f; const double PI = acos(-1.0); const double eps = 1e-8; const int maxn = 1e5 + 5; const int mod = 1e9 + 7; const int dr[] = {-1, 0, 1, 0}; const int dc[] = {0, 1, 0, -1}; const char *de[] = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"}; int n, m; const int mon[] = {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; const int monn[] = {0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; inline int Min(int a, int b){ return a < b ? a : b; } inline int Max(int a, int b){ return a > b ? a : b; } inline LL Min(LL a, LL b){ return a < b ? a : b; } inline LL Max(LL a, LL b){ return a > b ? a : b; } inline bool is_in(int r, int c){ return r >= 0 && r < n && c >= 0 && c < m; } int dp[10][2], a[10]; int dfs(int pos, bool is, bool ok){ if(!pos) return 1; int &ans = dp[pos][is]; if(!ok && ans >= 0) return ans; int res = 0, n = ok ? a[pos] : 9; for(int i = 0; i <= n; ++i){ if(4 == i || is && 2 == i) continue; res += dfs(pos-1, i == 6, ok && i == n); } if(!ok) ans = res; return res; } int solve(int n){ int len = 0; while(n){ a[++len] = n % 10; n /= 10; } return dfs(len, false, true); } int main(){ memset(dp, -1, sizeof dp); while(scanf("%d %d", &m, &n) == 2 && (m+n)){ printf("%d ", solve(n) - solve(m-1)); } return 0; }