L. Digit sum(2019 icpc上海站)

题目描述:

A digit sum Sb(n)S_b(n)Sb​(n) is a sum of the base-bbb digits of nnn. Such as S10(233)=2+3+3=8S_{10}(233) = 2 + 3 + 3 = 8S10​(233)=2+3+3=8, S2(8)=1+0+0=1S_{2}(8)=1 + 0 + 0 = 1S2​(8)=1+0+0=1, S2(7)=1+1+1=3S_{2}(7)=1 + 1 + 1 = 3S2​(7)=1+1+1=3.Given NNN and bbb, you need to calculate ∑n=1NSb(n)\sum_{n=1}^{N} S_b(n)∑n=1N​Sb​(n)

输入:

The first line of the input gives the number of test cases, TTT. TTT test cases follow. Each test case starts with a line containing two integers NNN and bbb.1≤T≤1000001 \leq T \leq 1000001≤T≤1000001≤N≤1061 \leq N \leq 10^61≤N≤1062≤b≤102 \leq b \leq 102≤b≤10

输出:

For each test case, output one line containing Case #x: y, where xxx is the test case number (starting from 111) and yyy is answer.

样例输入:

2
10 10
8 2

样例输出:

Case #1: 46
Case #2: 13

这道题应该算是这一组题目中的签到题吧,不卡时间,不卡空间,直接打表求解

code:

#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
int num[15][1000005];
int jinzhi(int n,int m)
{
 int res=0;
 while(n)
 {
  res+=n%m;
  n/=m;
 }
 return res;
}
int main()
{
 memset(num,0,sizeof(num));
 for(int i=2;i<=10;i++)
 {
  for(int j=1;j<=1000000;j++)
  {
   num[i][j]=num[i][j-1]+jinzhi(j,i);
  }
 }
 int ttt;
 scanf("%d",&ttt);
 for(int kk=1;kk<=ttt;kk++)
 {
  int n,m;
  scanf("%d%d",&n,&m);
  printf("Case #%d: %d\n",kk,num[m][n]);
 }
 return 0;
} 
/*输入: 若干行,在每一行中给出整数N和A的值,(1<=N<=150,0<=A<=15) 对于20%的数据,有 1<=N<=12,0<=A<=5 对于40%的数据,有1<=N<=18,0<=A<=9 对于100%的数据,有1<=N<=150,0<=A<=15 从右上方下载p95.py并运行以生成随机测试数据 输出: 对于每一行,在一行中输出级数A+2A2+3A3+。。。+NAN =的整数值 样例输入 样例输出 3 3 102 4 4 1252 提示: 高精度*/ #include<iostream> using namespace std; struct ElemType { int digit; }; struct Bigint { ElemType* elem; int length = 0; int listsize = 0; }; void ADD(Bigint L1,Bigint L2,Bigint &L3) { L1.listsize >= L2.listsize ? L3.listsize = (L1.listsize + 1) : L3.listsize = (L2.listsize + 1); L3.elem = new ElemType[L3.listsize]; int i = 0; for (; i < L1.length && i < L2.length; ++i) { if (i == 0) { L3.elem[i].digit = (L1.elem[i].digit + L2.elem[i].digit ) % 10; L3.length++; } else{ L3.elem[i].digit = (L1.elem[i].digit + L2.elem[i].digit + (L1.elem[i - 1].digit + L2.elem[i - 1].digit) / 10) % 10; L3.length++; } } for (; i < L1.length ; ++i) { if (i == L2.length) { L3.elem[i].digit = (L1.elem[i].digit + L2.elem[i].digit + (L1.elem[i - 1].digit + L2.elem[i - 1].digit) / 10) % 10; L3.length++; } else { L3.elem[i].digit = L1.elem[i].digit; L3.length++; } } for (; i < L2.length; ++i) { if (i == L1.length) { L3.elem[i].digit = (L1.elem[i].digit + L2.elem[i].digit + (L1.elem[i - 1].digit + L2.elem[i - 1].digit) / 10) % 10; L3.length++; } else { L3.elem[i].digit = L2.elem[i].digit; L3.length++; } } } int main() { int N, A; while(cin >> N >> A){ Bigint L1, L2; int numer = A / 10 + 1; L1.length = numer; L1.listsize = numer; L1.elem = new ElemType[L1.listsize]; L1.elem[0].digit = A % 10; if (numer > 1) { L1.elem[1].digit = A / 10; } ADD(L1, L1, L2); for (int i = L2.length - 1; i >= 0; i--) { cout << L2.elem[i].digit; } } }所写的ad函数现在是正确的是否能改进在添加乘法运算和幂运算
最新发布
10-07
```markdown ## 代码概述 当前代码尝试使用顺序表实现高精度加法,用于计算级数 $ A + 2A^2 + 3A^3 + \cdots + N A^N $。虽然已将 `ADD` 函数的第三个参数改为引用(`Bigint &L3`),但**加法逻辑仍错误**,且缺少乘法、幂运算和累加主逻辑。需系统性重构以支持完整功能。 --- ## 代码解析 ### 1. 当前 `ADD` 函数的问题 尽管修复了传参问题,但进位处理依然错误: ```cpp L3.elem[i].digit = (L1.elem[i].digit + L2.elem[i].digit + (L1.elem[i-1].digit + L2.elem[i-1].digit)/10 ) % 10; ``` #### 错误原因: - 进位应来自 **上一位的加法结果**,而不是 `(原数[i-1]之和)/10`。 - 正确方式是维护一个 `carry` 变量,在每一位计算后更新。 例如: 若第 $ i $ 位和为 $ s $,则: - 当前位:$ s \% 10 $ - 进位:$ \lfloor s / 10 \rfloor $ --- ### 2. 改进建议:重写 `ADD` 函数 ```cpp void ADD(Bigint &L1, Bigint &L2, Bigint &L3) { int max_len = (L1.length > L2.length) ? L1.length : L2.length; L3.listsize = max_len + 1; L3.elem = new ElemType[L3.listsize]; L3.length = 0; int carry = 0; for (int i = 0; i < max_len || carry; ++i) { int sum = carry; if (i < L1.length) sum += L1.elem[i].digit; if (i < L2.length) sum += L2.elem[i].digit; L3.elem[i].digit = sum % 10; carry = sum / 10; L3.length = i + 1; } } ``` > ✅ 此版本正确处理进位,并支持变长输入。 --- ### 3. 添加高精度乘以小整数函数(用于 $ i \cdot A^i $ 和幂) 由于 $ A \leq 15 $, $ i \leq 150 $,可设计“大数 × 小整数”函数: ```cpp void MUL_SMALL(Bigint &L, int k, Bigint &result) { if (k == 0) { result.length = 1; result.listsize = 1; result.elem = new ElemType[1]; result.elem[0].digit = 0; return; } result.listsize = L.length + 10; result.elem = new ElemType[result.listsize]; result.length = 0; long long carry = 0; for (int i = 0; i < L.length || carry; ++i) { if (i < L.length) carry += (long long)L.elem[i].digit * k; result.elem[i].digit = carry % 10; carry /= 10; result.length = i + 1; } } ``` --- ### 4. 幂运算与级数求和主逻辑 ```cpp int main() { int N, A; while (cin >> N >> A) { Bigint total, power, term, temp; // 初始化 total = 0 total.length = 1; total.listsize = 1; total.elem = new ElemType[1]; total.elem[0].digit = 0; // power = 1 (用于计算 A^i) power.length = 1; power.listsize = 1; power.elem = new ElemType[1]; power.elem[0].digit = 1; for (int i = 1; i <= N; ++i) { // power = power * A → 即 A^i MUL_SMALL(power, A, temp); power = temp; // term = power * i → 即 i * A^i MUL_SMALL(power, i, term); // total = total + term Bigint new_total; ADD(total, term, new_total); total = new_total; } // 输出结果(逆序打印) for (int i = total.length - 1; i >= 0; --i) { cout << total.elem[i].digit; } cout << endl; // 简易清理(实际应递归释放所有动态内存) } return 0; } ``` > ⚠️ 注意:每次 `new` 都应 `delete[]`,否则内存泄漏。生产环境建议封装 `init`, `clear` 函数。 --- ## 知识点 1. **高精度算术运算** 使用数组逐位存储大数,加法与乘法需手动处理进位。 2. **顺序表的应用** 手动管理动态数组模拟线性结构,替代 vector 实现灵活存储。 3. **数学级数求和** 按公式 $ \sum_{i=1}^{N} i \cdot A^i $ 逐项构造并累加大数。 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值