P1009 [NOIP 1998 普及组] 阶乘之和
题目描述
用高精度计算出 S = 1! + 2! + 3! +… + n!
输入格式
一个正整数 n。
输出格式
一个正整数 S,表示计算结果。
输入输出样例
输入
3
输出
9
说明/提示
【数据范围】
对于 100 % 的数据, 1 <= n <= 50。
【其他说明】
注,《深入浅出基础篇》中使用本题作为例题,但是其数据范围只有 $n \le 20$,使用书中的代码无法通过本题。
如果希望通过本题,请继续学习第八章高精度的知识。
NOIP1998 普及组 第二题
版本1:
#include<iostream>
using namespace std;
int main(){
int num;
cin>>num;
long long total=num;
for(int i = num-1;i>=1;i--){
total=(total+1)*i;
}
cout<<total;
return 0;
}
最多到26
版本2,依旧溢出,大概到40多
#include<iostream>
using namespace std;
void print(__int128 x) {
if (x > 9) print(x / 10);
cout << (char)(x % 10 + '0');
}
int main() {
int num;
cin >> num;
__int128 total = num;
for (int i = num - 1; i >= 1; i--) {
total = (total + 1) * i;
}
print(total);
return 0;
}
版本3
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
// 极简函数1:超大数字符串 + 1 (适配你的公式里的 total+1)
string strAddOne(string s) {
reverse(s.begin(), s.end()); // 反转,从个位开始算,方便进位
int carry = 1; // 要加的1,初始进位就是1
for(int i=0; i<s.size() && carry; i++) {
int num = s[i]-'0' + carry;
s[i] = num%10 + '0';
carry = num/10;
}
if(carry) s += '1'; // 最后还有进位,补1
reverse(s.begin(), s.end()); // 反转回来
return s;
}
// 极简函数2:超大数字符串 × 普通整数 (适配你的公式里的 *i)
string strMulInt(string s, int n) {
reverse(s.begin(), s.end());
string res;
int carry = 0;
for(int i=0; i<s.size(); i++) {
int num = (s[i]-'0')*n + carry;
res += num%10 + '0';
carry = num/10;
}
while(carry) { // 处理剩余进位
res += carry%10 + '0';
carry /= 10;
}
reverse(res.begin(), res.end());
return res;
}
int main() {
int num;
cin >> num;
string total = to_string(num); // 字符串存初始值,替代__int128
// ===== 你的原循环+原公式,一字未改!=====
for (int i = num - 1; i >= 1; i--) {
total = strMulInt( strAddOne(total) , i );
}
cout << total << endl; // 直接cout输出字符串,无需额外打印函数
return 0;
}
阴中阴