列表

详情


NC221175. 小圆前辈的888

描述

在中国数字8都会受到很多人的喜爱,因为8寓意着发财,小圆前辈也想发财。
小圆前辈希望你告诉她,1到n中所有数的价值之和。
定义:
对于个位不是8的数字,价值为0。
对于个位是8的数字,其价值为此数字各数位数字之和。
例如: 6868,个位数是8, 所以它的价值就是6+8+6+8=28,而998244353它的价值是0,因为它的个位数字不是8。
现在给你一个整数n,让你求1到n所有数的价值之和, 答案模上

输入描述

第一行一个整数n ()。

输出描述

一个整数,表示1到n的所有数的价值和。

示例1

输入:

20

输出:

17

说明:

1到20只有8, 18有价值,答案为:8 + 1 + 8 = 17

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(g++ 7.5.0) 解法, 执行用时: 80ms, 内存消耗: 19916K, 提交时间: 2023-07-11 13:46:02

#include <iostream>

using namespace std;

const int N = 200010;
const int mod = 1e9 + 7;

string s;

struct State {  
  int cnt, sum;
  State() = default;
  State(int cnt) : cnt(cnt) { sum = 0; }
  State operator+=(const State &oth) {
    (cnt += oth.cnt) %= mod;
    (sum += oth.sum) %= mod;
    return *this;
  }
  State operator+= (const int &k) {
    (sum += 1ll * k * cnt % mod) %= mod;
    return *this;
  }
} f[N][2];
bool vis[N][2];

State dfs(int pos, bool lim, int lst) {
  if (pos == size(s)) return lst == 8;
  State& v = f[pos][lim];
  if (vis[pos][lim]) return v;
  vis[pos][lim] = true;
  State res = 0;
  int upper = lim ? s[pos] - '0' : 9;
  for (int i = 0; i <= upper; i++) {
    bool nlim = lim and (i == s[pos] - '0');
    res += dfs(pos + 1, nlim, i) += i;
  }
  return v = res;
}


int main() {
  cin >> s;
  cout << dfs(0, true, -1).sum;
  return 0;
}

C++(clang++11) 解法, 执行用时: 16ms, 内存消耗: 5572K, 提交时间: 2021-05-13 19:15:39

#include <bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10;
using ll = long long;
const ll mod = 1e9 + 7;
char a[N];
ll f[N][2];
ll g[N];
int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> (a + 1);
    int n = strlen(a + 1);
    for (int i = 1; i < n; ++i) {
        int cur = a[i] - '0';
        f[i][0] = (f[i - 1][0] * 10 + g[i - 1] * 45 + f[i - 1][1] * cur + cur * (cur - 1) / 2 ) % mod;
        f[i][1] = (f[i - 1][1] + cur) % mod;
        g[i] = (g[i - 1] * 10 + cur) % mod;
    }
 
    cout << (f[n - 1][0] + g[n - 1] * 8 + (a[n] - '0' < 8 ? 0 : f[n - 1][1] + 8)) % mod;
}

上一题