求助此题我记忆化搜索的正确性。
  • 板块CF1073E Segment Sum
  • 楼主shyr
  • 当前回复15
  • 已保存回复15
  • 发布时间2022/2/5 22:42
  • 上次更新2023/10/28 09:37:38
查看原帖
求助此题我记忆化搜索的正确性。
357163
shyr楼主2022/2/5 22:42

代码如下,相当于将状压暴力拆开,不加记搜没错,可是加了记搜结果是错的。

没看懂题解的记忆化数组,想问的问题就是如果不记 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 个相当于状压作用,判断这个数是否存在。
2022/2/5 22:42
加载中...