鱼C论坛

 找回密码
 立即注册
查看: 260|回复: 3

求1到n的数位和,要求O(n)的复杂度

[复制链接]
发表于 2024-2-20 00:06:23 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
  1. #include <iostream>
  2. using namespace std;

  3. int f(int n)
  4. {
  5.     string str = to_string(n);
  6.     int sum_1 = 0;
  7.     for (char ch : str) {
  8.         sum_1 += ch - '0';
  9.     }
  10.     return sum_1;
  11. }

  12. void solve()
  13. {
  14.     long long n;
  15.     cin >> n;
  16.     long long sum = 0;
  17.     for (int i = 1; i <= n; i++) {
  18.         sum += f(i);
  19.     }
  20.     cout << sum << endl;
  21. }参考代码如下

  22. int main()
  23. {
  24.     int t;
  25.     cin >> t;
  26.     while (t--) {
  27.         solve();
  28.     }
  29.     return 0;
  30. }
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-2-20 00:06:47 | 显示全部楼层
题目要求计算从1到n的数位和,要求复杂度为O(n)。下面是一个符合要求的解法。

首先,我们可以观察到从1到n的每个数字的数位和都是从1到n最高位的数位和的累加。例如,从1到100的数位和等于从1到99的数位和加上100的数位和。因此,我们可以使用动态规划来解决这个问题。

具体的步骤如下:

1. 创建一个长度为n+1的数组sums,用来存储从1到n的每个数字的数位和。
2. 初始化sums[0]为0。
3. 从1到n,遍历每个数字i:
   a. 获取数字i的最低位digit:digit = i % 10。
   b. 更新数字i的数位和为sums = sums[i / 10] + digit。
4. 返回sums[n]作为结果。

下面是对应的C++代码:

  1. #include <iostream>
  2. #include <vector>
  3. using namespace std;

  4. int getDigitSum(int n) {
  5.     vector<int> sums(n+1, 0);
  6.     for (int i = 1; i <= n; i++) {
  7.         int digit = i % 10;
  8.         sums[i] = sums[i / 10] + digit;
  9.     }
  10.     return sums[n];
  11. }

  12. int main() {
  13.     int n;
  14.     cout << "请输入一个整数n:";
  15.     cin >> n;
  16.     int result = getDigitSum(n);
  17.     cout << "从1到" << n << "的数位和为:" << result << endl;
  18.     return 0;
  19. }
复制代码


这段代码中,我们首先定义了一个名为getDigitSum的函数,用来计算从1到n的数位和。在主函数中,我们输入一个整数n,并调用getDigitSum函数来计算结果,然后输出结果。

希望对你有帮助!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-2-20 12:01:12 | 显示全部楼层
1:将数字转换成str
2:数一下位数(strlen)
3:输出45*1+45*11+45*111+…+45*111(strlen个1)111
4:试一下!!
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-2-24 09:57:58 | 显示全部楼层
本帖最后由 zhangjinxuan 于 2024-2-24 10:00 编辑

严格来说不会有 $O(n)$ 的时间复杂度,这个代码还是 $O(n \log_{10} n)$ 的复杂度。

不过你可以使用数位DP将时间复杂度做到 $O(\log_{10} n)$,虽然并不是楼主需要的 $O(n)$,但是这个算法比 $O(n)$ 算法优秀得多,可以解决 $n=10^{18}$ 甚至更大的情况。

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define int long long
  4. int d[18], m;
  5. long long l, r;

  6. struct Info {
  7.         int a[10], numtot;
  8.         const Info operator + (const Info &i) const {
  9.                 Info res = {{}, numtot + i.numtot};
  10.                 for (int j = 0; j <= 9; ++j) res.a[j] = a[j] + i.a[j];
  11.                 return res;
  12.         }
  13.         const Info operator - (const Info &i) const {
  14.                 Info res = {{}, numtot - i.numtot};
  15.                 for (int j = 0; j <= 9; ++j) res.a[j] = a[j] - i.a[j];
  16.                 return res;
  17.         }
  18. } f[21][2][2];

  19. Info calc(int i, int zero, int limited) {
  20.         if (i == m + 1) return {{}, zero};
  21.         if (f[i][zero][limited].numtot != -1) return f[i][zero][limited];
  22.         Info res = {{}, 0};
  23.         if (i == 1) {
  24.                 for (int j = 0; j <= d[1]; ++j) {
  25.                         Info tmp = calc(i + 1, (j != 0), (j != d[1]));
  26.                         res = res + tmp;
  27.                         if (j != 0) {
  28.                                 res.a[j] += tmp.numtot;
  29.                         }
  30.                 }
  31.         } else {
  32.                 if (limited) {
  33.                         for (int j = 0; j <= 9; ++j) {
  34.                                 Info tmp = calc(i + 1, (bool)(zero | j), 1);
  35.                                         res = res + tmp;
  36.                                 if ((bool)(zero | j)) {
  37.                                 res.a[j] += tmp.numtot;
  38.                                 }
  39.                         }
  40.                 } else { // ???üì? 0 ~ d[i] μ?????£?2¢?ú×?òa?ó
  41.                         for (int j = 0; j <= d[i]; ++j) {
  42.                                 Info tmp = calc(i + 1, (bool)(zero | j), (j != d[i]));
  43.                                         res = res + tmp;
  44.                                 if ((bool)(zero | j)) {
  45.                                 res.a[j] += tmp.numtot;
  46.                                 }
  47.                         }
  48.                 }
  49.         }
  50.         return f[i][zero][limited] = res;
  51. }

  52. signed main() {
  53.     int t = 1;
  54.         while (t--) {
  55.             l = 1;
  56.             scanf("%lld", &l, &r);
  57.                 m = 0;
  58.                 for (long long tr = r; tr; tr /= 10)
  59.                         d[++m] = tr % 10;
  60.                 for (int i = 1, j = m; i < j; ++i, --j) swap(d[i], d[j]);
  61.                 for (int i = 0; i < 21; ++i) for (int j = 0; j < 2; ++j) for (int k = 0; k < 2; ++k) f[i][j][k].numtot = -1;
  62.                 Info tmp = calc(1, 0, 0);
  63.                 if (l != 1) {
  64.                         m = 0;
  65.                         memset(d, 255, sizeof(d));
  66.                         for (long long tr = l - 1; tr; tr /= 10)
  67.                                 d[++m] = tr % 10;
  68.                         for (int i = 1, j = m; i < j; ++i, --j) swap(d[i], d[j]);
  69.                 for (int i = 0; i < 21; ++i) for (int j = 0; j < 2; ++j) for (int k = 0; k < 2; ++k) f[i][j][k].numtot = -1;
  70.                         tmp = tmp - calc(1, 0, 0);
  71.                 }
  72.                 long long res = 0;
  73.                 for (int i = 1; i <= 9; ++i) res += tmp.a[i] * i;
  74.                 printf("%lld\n", res);
  75.         }
  76. //        printf("%lld\n", tmp.numtot);
  77.         return 0;
  78. }
  79. /*
  80. 01
  81. */
复制代码
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-28 04:36

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表