题目链接:点击打开链接
思路:
我们用dp[cur][a][b][c][d][p]表示当前到了第cur位,前四位分别是abcd并且当前是否已经小于给定的数的方案数。 我们分别算出L和R的dp值, 以及L是否符合要求, 做差并把多减的加上即可。 比赛时写的比较恶心, 不是很美观但是很直观。
细节参见代码:
#include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <string> #include <vector> #include <stack> #include <bitset> #include <cstdlib> #include <cmath> #include <set> #include <list> #include <deque> #include <map> #include <queue> #define Max(a,b) ((a)>(b)?(a):(b)) #define Min(a,b) ((a)<(b)?(a):(b)) using namespace std; typedef long long ll; typedef long double ld; const double eps = 1e-6; const double PI = acos(-1); const int mod = 1e9 + 7; const int INF = 0x3f3f3f3f; const int seed = 131; const ll INF64 = ll(1e18); const int maxn = 11; int n, m, v,cnt= 0, sum[maxn]; ll L, R, B[33], C[33], dp[19][maxn][maxn][maxn][maxn][2], vis[19][maxn][maxn][maxn][maxn][2]; int k, kase = 0, q, id; ll dp1(int cur, int a, int b, int c, int d, int p) { ll& ans = dp[cur][a][b][c][d][p]; if(cur == cnt) return 1LL; if(vis[cur][a][b][c][d][p] == kase) return ans; vis[cur][a][b][c][d][p] = kase; ans = 0; if(p) { for(int i = 0; i < 10; i++) { if(k == 2) { if(d == i) continue; } else if(k == 3) { if(c == i || d == i) continue; } else if(k == 4) { if(b == i || c == i || d == i) continue; } else { if(a == i || b == i || c == i || d == i) continue; } if(i == 0) { if(d == 10) ans += dp1(cur+1, a, b, c, d, p); else ans += dp1(cur+1, b, c, d, i, p); } else ans += dp1(cur+1, b, c, d, i, p); } } else { for(int i = 0; i < 10; i++) { if(k == 2) { if(d == i) continue; } else if(k == 3) { if(c == i || d == i) continue; } else if(k == 4) { if(b == i || c == i || d == i) continue; } else { if(a == i || b == i || c == i || d == i) continue; } if(i < B[cur]) { if(i == 0) { if(d == 10) ans += dp1(cur+1, a, b, c,d, 1); else ans += dp1(cur+1, b, c,d, i, 1); } else ans += dp1(cur+1, b, c,d, i, 1); } else if(i == B[cur]) { if(i == 0) { if(d == 10) ans += dp1(cur + 1, a, b, c, d, p); else ans += dp1(cur+1, b, c, d, i, p); } else ans += dp1(cur+1, b, c, d, i, p); } } } return ans; } bool ok() { for(int i = 0; i < cnt; i++) { for(int j = i-1; j >= max(0, i-(k-1)); j--) { if(B[j] == B[i]) return false; } } return true; } int main() { while(~scanf("%I64d%I64d%d", &L, &R, &k)) { ++kase; ll cur = R; int cc = 0; cnt = 0; while(cur) { C[cc++] = cur % 10; cur /= 10; } for(int i = cc-1; i >= 0; i--) { B[cnt++] = C[i]; } ll ans1 = dp1(0, 10, 10, 10, 10, 0); cc = 0; cnt = 0; cur = L; while(cur) { C[cc++] = cur % 10; cur /= 10; } for(int i = cc-1; i >= 0; i--) B[cnt++] = C[i]; ++kase; ll ans2 = dp1(0, 10, 10, 10, 10, 0); if(ok()) printf("%I64d\n", ans1 - ans2 + 1); else printf("%I64d\n", ans1 - ans2); } return 0; }
时间: 2024-10-11 17:36:27