P8680 [蓝桥杯 2019 省 B] 特别数的和
暴力秒了
#include<bits/stdc++.h> #define int long long//开long long是个好习惯 using namespace std; bool baozi(int x) { while(x) { int t = x % 10; if(t == 2 || t == 0 || t == 1 || t == 9) //数位判断 { return true; } x /= 10; } return false; } signed main() { int n , sum = 0; cin >> n; for(int i = 1;i <= n;i++) { if(baozi(i))//如果条件成立, 就让sum加上i { sum += i; } } cout << sum << endl;//最后输出所有满足条件的数的和 return 0; }
但是写的数位dp做法调不出来😂 只有50分
#include <iostream> #include <stdio.h> #include <algorithm> #include <string> #include <cmath> #define For(i, j, n) for(int i = j ; i <= n ; ++i) using namespace std; int k, tar; long long ans; short flag; int f(int x) { if(x == 0) return 0; if(x == 1) return 1; if(x == 2) return 2; if(x == 9) return 3; return -1; } int powers[] = {1, 10, 100, 1000, 10000}; void solve(int n, int res, int p0, int p1, bool suc) { if(res > tar) return; if(n == k + 1) { // cout << res << " " << flag << " " << suc << endl; if(flag && !(flag == 1 && !suc)) ans += res; return; } for(int i = 0; i <= 9; i++) { int t = f(i); short b = flag; if(t >= 0) flag |= (1 << t); int t0 = ((!i)?n:p0); int t1 = (i?n:p1); solve(n + 1, res + i * powers[n - 1], t0, t1, suc | (t1 > t0)); flag = b; } } int main() { cin >> tar; k = log10(tar) + 1; solve(1, 0, 1, 0, 0); cout << ans << endl; return 0; }
更新:换了种写法,数位dp做法过了,核心思想:do it simple
#include <iostream> #include <stdio.h> #include <algorithm> #include <string> #include <cmath> #define For(i, j, n) for(int i = j ; i <= n ; ++i) using namespace std; int k, tar; long long ans; int powers[] = {1, 10, 100, 1000, 10000}; void solve(int n, int res, int last, bool suc) { if(res > tar) return; if(n == k + 1) { // cout << res << " " << " " << suc << endl; if(suc) ans += res; return; } for(int i = 0; i <= 9; i++) { bool f = false; if(i == 1 || i == 2 || i == 9) f = true; if(i > 0 && last == 0) f = true; solve(n + 1, res + i * powers[n - 1], i, suc | f); } } int main() { cin >> tar; k = log10(tar) + 1; solve(1, 0, -1, 0); cout << ans << endl; return 0; }
注意last的初值不能为0,必须设置成一个负数,否则答案会偏大。
但事实上,这道题并不适合用数位dp来做,数位dp适合的场景:
数据范围非常大,且题目给出的条件很复杂,不好直接验证,于是我们直接按照这个规则来构造数字。