解题报告 『不要62(数位动规)』

原题地址

又学会了骂人的新词语。

代码实现如下:

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (register int i = (a); i <= (b); i++)

const int maxn = 10;

int l, r, ans, len;
int num[maxn], dp[maxn][maxn];

void origin() {memset(dp, -1, sizeof(dp));}

int dfs(int pos, int limit, int lead, int is_six) {
    int ans = 0;
    if (!pos) return 1;
    if (!limit && !lead && dp[pos][is_six] != -1) return dp[pos][is_six];
    int res = limit ? num[pos] : 9;
    rep(i, 0, res) {
        if (i == 4 || (is_six && i == 2)) continue;
        if (!i && lead) ans += dfs(pos - 1, (i == res) && limit, 0, i == 6);
        else ans += dfs(pos - 1, (i == res) && limit, 1, i == 6);
    }
    if (!limit && !lead) dp[pos][is_six] = ans;
    return ans;
}

int work(int x) {
    origin();
    len = 0;
    while (x) {
        num[++len] = x % 10;
        x /= 10;
    }
    return dfs(len, 1, 1, 0);
}

void write(int x) {
    if (x < 0) {
        putchar(‘-‘);
        x = -x;
    }
    if (x > 9) write(x / 10);
    putchar(x % 10 + ‘0‘);
}

int main() {
    while (scanf("%d%d", &l, &r) && l && r) {
        write(work(r) - work(l - 1));
        printf("\n");
    }
    return 0;
}

但实际上我更习惯顺着搜:

#include <bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for (register int i = (a); i <= (b); i++)

const int maxn = 10;

int l, r, ans, len;
int num[maxn], dp[maxn][maxn];

void origin() {memset(dp, -1, sizeof(dp));}

int dfs(int pos, int limit, int lead, int is_six) {
    int ans = 0;
    if (pos > len) return 1;
    if (!limit && !lead && dp[pos][is_six] != -1) return dp[pos][is_six];
    int res = limit ? num[len - pos + 1] : 9;
    rep(i, 0, res) {
        if (i == 4 || (is_six && i == 2)) continue;
        if (!i && lead) ans += dfs(pos + 1, (i == res) && limit, 0, i == 6);
        else ans += dfs(pos + 1, (i == res) && limit, 1, i == 6);
    }
    if (!limit && !lead) dp[pos][is_six] = ans;
    return ans;
}

int work(int x) {
    origin();
    len = 0;
    while (x) {
        num[++len] = x % 10;
        x /= 10;
    }
    return dfs(1, 1, 1, 0);
}

void write(int x) {
    if (x < 0) {
        putchar(‘-‘);
        x = -x;
    }
    if (x > 9) write(x / 10);
    putchar(x % 10 + ‘0‘);
}

int main() {
    while (scanf("%d%d", &l, &r) && l && r) {
        write(work(r) - work(l - 1));
        printf("\n");
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Kirisame-Marisa/p/11005865.html

时间: 2024-08-30 17:20:01

解题报告 『不要62(数位动规)』的相关文章

解题报告 『占卜DIY(模拟)』

原题地址 水题,纯模拟. 代码实现如下: #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (register int i = a; i <= b; i++) #define per(i, a, b) for (register int i = a; i >= b; i--) const int maxn = 15; int ans = 0; int num[maxn], mat[maxn]

解题报告 『统计单词数(字符串)』

原题地址 字符串入门题,因为完全不擅长所以还是WA了好几次才过. 还犯了一个⑨错误,果然做题时不应该听<チルノのパーフェクトさんすう教室>…… 代码如下: #include <bits/stdc++.h> using namespace std; void write(int x) { if (x < 0) { putchar('-'); x = -x; } if (x > 9) write(x / 10); putchar(x % 10 + '0'); } int m

解题报告 『酒店之王(网络最大流 + 拆点)』

原题地址 网络流板子题 + 拆点,个人觉得蓝题比较合适. 尽管我一开始只得了10分. 具体还是看代码吧. 代码实现如下: #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (register int i = a; i <= b; i++) const int inf = 0x3f3f3f3f, maxn = 1e4 + 5; int n, p, q, S, T, ans = 0, num_edge

解题报告 『[USACO07JAN]Tallest Cow(差分)』

原题地址 建立一个数组high,若一对关系指明Ai与Bi可以互相看见(Ai < Bi),则把数组high中下标为Ai + 1到Bi - 1的数都减去1,意为Ai到Bi之间的牛的身高至少比它们少1. 再加一个辅助数组sup可以将时间复杂度由O(NM)降到O(N + M). 代码实现如下: #include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (register int i = a; i <= b;

解题报告 『Raid(分治)』

原题地址 大概翻译一下题意: 在与联邦的战争接连失败之后,帝国方面撤退到了最后的据点.凭借着强大的防御系统,帝国军击退了联邦的六波进攻.经过几天不眠不休的思考,Arthur,联邦统帅,注意到防御系统的唯一弱点是它的能源供应.该系统由n个核电站进行充电,任何一个核电站的故障都会导致系统失效. 将军很快就发动了一次突袭,突袭者是准备潜行进入要塞的N名特工.不幸的是,由于帝国空军的攻击,他们未能按预期的位置着陆.作为一名经验丰富的将军,Arthur很快意识到他需要重新安排计划.他现在想知道的第一件事是

解题报告 『HISTOGRA - Largest Rectangle in a Histogram(单调栈)』

原题地址 单调栈板子题,代码很简单. 注意将a[n + 1]赋值为0,防止栈中矩形未弹完. 代码实现如下: #include <bits/stdc++.h> using namespace std; #define LL long long #define rep(i, a, b) for (register int i = a; i <= b; i++) const int maxn = 1e5 + 5; int n; int a[maxn], sta[maxn], wid[maxn]

解题报告 『矿洞:坍塌(ODT)』

原题地址 退役第二天也要坚持用珂朵莉树水题. 代码实现如下: #include <bits/stdc++.h> using namespace std; #define IT set<node>::iterator #define rep(i, a, b) for (register int i = (a); i <= (b); i++) const int maxn = 5e5 + 5; int n, m, cnt = 1; char str[maxn]; struct n

Fixed Point 解题报告

题目总结: 这种数论动规的关键点是在“与上届相等的数的处理”上,只要这个弄懂了,这种题应该就都会做了. 因为和上届相等的数最多只有一个,所以我用一个equal来记录是否有满足条件的上届.而其他小于上届的数用f数组储存. 策略只有取1和取0. 小于上届的数可以随便取. equal的状态转移要好好想想: 当前位为1:取1则equal保留,取0则equal可以转移到f数组. 当前位为0:取0则equal保留.取1就比上届大了,舍去. 一般性总结: 1.打草稿分析样例很有效果. 2.直接用不加证明的结论

动规,模拟,递推,最长公共子序列

题目链接:http://poj.org/problem?id=1458 解题报告: 1.用二维数组模拟两个字符串上每个子串对应的最长公共子序列. 2.显然,就是要求二维数组最右下的数字 3.递推公式: if(s1[i-1]==s2[j-1]) maxlen[i][j]=maxlen[i-1][j-1]+1; else maxlen[i][j]=max(maxlen[i][j-1],maxlen[i-1][j]); Memory: 1024KTime: 0MSLanguage: C++Result