代码如下,相当于将状压暴力拆开,不加记搜没错,可是加了记搜结果是错的。
没看懂题解的记忆化数组,想问的问题就是如果不记 sum 是否有问题?
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 998244353;
int a[25], cnt, K;
ll l, r, f[11][2][2][2][2][2][2][2][2][2][2][2][2];
inline int read(){
int x = 0,f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-')
f = -1;
ch = getchar();
}
while(ch >= '0' && ch <= '9'){
x = (x << 1) + (x << 3) + (ch ^ 48);
ch = getchar();
}
return x * f;
}
inline void write(int x)
{
char F[200];
int tmp = x > 0 ? x : -x;
if(x<0) putchar('-');
int cnt = 0;
while(tmp > 0){
F[cnt++] = tmp%10+'0';
tmp /= 10;
}
while(cnt > 0) putchar(F[--cnt]);
putchar('\n');
}
namespace solvtion{
ll dfs(int k, int p, int q, ll sum, int ze, int o, int e, int s, int si, int wu, int liu, int qi, int ba, int jiu){
int c = 0;
if(ze) c++; if(o) c++; if(e) c++; if(s) c++; if(si) c++; if(wu) c++; if(liu) c++; if(qi) c++; if(ba) c++; if(jiu) c++;
if(f[k][p][q][ze][o][e][s][si][wu][liu][qi][ba][jiu] != -1) return f[k][p][q][ze][o][e][s][si][wu][liu][qi][ba][jiu];
// printf("%d %d %d %d %lld\n", k, p, q, c, sum);
if(c > K) return 0;
if(!k){
return sum % mod;
}
ll ans = 0;
for(int i = 0; i <= 9; ++i){
if(!p && i > a[k]) break;
if(q || i){
ans += dfs(k - 1, p || (i < a[k]), q || i, sum * 10 + i, ze | (!i), o | (i == 1), e | (i == 2), s | (i == 3), si | (i == 4), wu | (i == 5), liu | (i == 6), qi | (i == 7), ba | (i == 8), jiu | (i == 9));
}
else ans += dfs(k - 1, p || (i < a[k]), q || i, sum * 10 + i, ze, o, e, s, si, wu, liu, qi, ba, jiu);
ans %= mod;
}
return f[k][p][q][ze][o][e][s][si][wu][liu][qi][ba][jiu] = (ans % mod);
}
ll calc(ll x){
memset(f, -1, sizeof(f));
cnt = 0;
while(x){
a[++cnt] = x % 10;
x /= 10;
}
return dfs(cnt, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0) % mod;
}
}
using namespace solvtion;
int main(){
scanf("%lld%lld%d", &l, &r, &K);
printf("%lld\n", calc(r) - calc(l - 1));
return 0;
}
//k 是填到第几位,p 是是否填的上一位是最高位,q 是判断前导零,后面 9 个相当于状压作用,判断这个数是否存在。