数位DP貌似很弱,先切水的练练手~
HDU2089:点击打开链接
输出区间里面没有连续62,没有4的数字个数.
#include <bits/stdc++.h> using namespace std; long long n, m; int bit[11], l; int dp[11][2]; int dfs (int pos, bool f1, bool f2) {//当前的位数 前一个数是不是6 是不是可以取到9 if (pos == 0) return 1; if (f2 && dp[pos][f1] != -1) { return dp[pos][f1]; } int Max = (f2 ? 9 : bit[pos]), ans = 0; for (int i = 0; i <= Max; i++) { if (i == 4 || (f1 && i == 2)) continue; ans += dfs (pos-1, i==6, f2 || i<Max); } if (f2) dp[pos][f1] = ans; return ans; } long long f (long long num) { l = 0; while (num) { bit[++l] = num%10; num /= 10; } return dfs (l, 0, 0); } int main () { memset (dp, -1, sizeof dp); while (cin >> n >> m && n+m) { cout << f (m)-f (n-1) << endl; } return 0; }
HDU3555:点击打开链接
1到n中没有连续49的数字个数.
同样
#include <bits/stdc++.h> using namespace std; typedef unsigned long long ull; ull n; int bit[11], l; ull dp[22][2]; ull dfs (int pos, bool f1, bool f2) {//当前的位数 前一个数是不是4 是不是可以取到9 if (pos == 0) return 1LL*1; if (f2 && dp[pos][f1] != -1) { return dp[pos][f1]; } int Max = (f2 ? 9 : bit[pos]); ull ans = 0; for (int i = 0; i <= Max; i++) { if (f1 && i == 9) continue; ans += dfs (pos-1, i==4, f2 || i<Max); } if (f2) dp[pos][f1] = ans; return ans; } long long f (long long num) { l = 0; while (num) { bit[++l] = num%10; num /= 10; } return dfs (l, 0, 0); } int main () { //cout << (((ull)1<<63)-1) << endl; memset (dp, -1, sizeof dp); int t; cin >> t; while (t--) { cin >> n; cout << n-f (n)+1 << endl; } return 0; }
UVA11361:点击打开链接
求所有位数和以及本身模k等于0的数的个数.
很相似,dfs的时候记录到当前位之前所有位数模k的余数m1和到当前位之前后面全部补0的余数m2,
转移方程就是dp(pos,m1,m2) = sigma {dp(pos-1, (m1-i)%k, (m2-i*10^pos-1)%k)}.
#include <bits/stdc++.h> using namespace std; long long n, m, mod; int bit[11], l; long long dp[12][111][111]; #define pow Pow long long pow[13]; long long dfs (int pos, long long m1, long long m2, bool f2) {//当前的位数 所有的数位和模m余m1 后面的数字模m余m2 是不是可以取到9 if (pos == 0) { if (m1 == 0 && m2 == 0) return 1; return 0; } if (f2 && dp[pos][m1][m2] != -1) { return dp[pos][m1][m2]; } long long Max = (f2 ? 9 : bit[pos]); long long ans = 0; for (long long i = 0; i <= Max; i++) { ans += dfs (pos-1, (m1-i+mod)%mod, ((m2-i*pow[pos-1])%mod+mod)%mod, f2 || i < Max); } if (f2) dp[pos][m1][m2] = ans; return ans; } long long f (long long num) { l = 0; while (num) { bit[++l] = num%10; num /= 10; } if (l*9 < mod) { return 1;//只能是0 } return dfs (l, 0, 0, 0); } int main () { pow[0] = 1; for (long long i = 1; i <= 11; i++) pow[i] = pow[i-1]*10; int t; cin >> t; while (t--) { cin >> n >> m >> mod; memset (dp, -1, sizeof dp); cout << f (m) - f(n-1) << endl; } return 0; }