[BZOJ1026][SCOI2009]windy数 && 数位DP

来源:互联网 发布:python 最大似然估计 编辑:程序博客网 时间:2024/04/29 08:06

不允许前导0的存在 所以先把首位非0的都统计出来 然后在把首位填上非0的数 后面的数就可以自由选择了

#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int MAXN = 15;int d[MAXN+10][MAXN+10], Cur[MAXN+10];inline int abs(int x) { return x < 0 ? -x : x; }void init(){for(int i = 0; i <= 9; i++) d[1][i] = 1;for(int i = 2; i <= MAXN; i++)for(int j = 0; j <= 9; j++)for(int k = 0; k <= 9; k++)if(abs(j-k) >= 2)d[i][j] += d[i-1][k];}int solve(int x){int Len = 0, ans = 0;memset(Cur, 0, sizeof(Cur));while(x) {Cur[++Len] = x % 10;x /= 10;}for(int i = 1; i <= Len-1; i++)for(int j = 1; j <= 9; j++)ans += d[i][j];for(int i = 1; i < Cur[Len]; i++) ans += d[Len][i];for(int i = Len-1; i >= 1; i--){for(int j = 0; j < Cur[i]; j++)if(abs(j - Cur[i+1]) >= 2)ans += d[i][j];if(abs(Cur[i] - Cur[i+1]) < 2) break;}return ans;}int main(){int L, R;init();scanf("%d%d", &L, &R);int ans = solve(R+1) - solve(L);printf("%d", ans);}

记忆化搜索版

#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>#include<queue>#define SF scanf#define PF printfusing namespace std;typedef long long LL;const int MAXN = 15;int d[MAXN+10][MAXN+10], bit[MAXN+10], tot[MAXN+10];int f[MAXN+10][MAXN][2][2];int R, L;int div(LL x) {int len = 0;while(x) {bit[++len] = x % 10; x /= 10;}return len;}int dp(int cur, int x, bool lim, bool fir) {if(cur == 0) return 1;if(f[cur][x][lim][fir]) return f[cur][x][lim][fir];int ret = 0, ed = lim ? bit[cur] : 9;for(int i = 0; i <= ed; i++) {if(!fir && abs(i-x) < 2) continue;ret += dp(cur-1, i, lim && i==ed, fir&&i==0);}return f[cur][x][lim][fir] = ret;}int main() {SF("%d%d", &L, &R);int len = div(R), ans = 0;ans += dp(len, 0, true, true);len = div(L-1);ans -= dp(len, 0, true, true);PF("%d", ans);}


0 0
原创粉丝点击