第十三题
3-11阶乘和加强版难度系数2 阶乘和 (10分)
这题很有意思
乍一看,20000000!两千万的阶乘,这数字,简直不敢想象
等等,我们需要输出20000000!的数吗?
不用
再一看,是输出的数和1000000007求模的结果
这肯定有猫腻 技巧
接下来,隆重介绍——同余定理
我们主要运用同余定理中的同余式相乘性质
若a≡b(mod m),c≡d(mod m),则ac≡bd(mod m)
举个例子吧
计算(2^15)mod23
2**15 % 23 // python的表达
=(32**3) % 23 // 同余的运用,32≡9(mod 23)
=9**3 % 23
=81*9 % 23 // 81≡12(mod 23)
=12*9 % 23
=108 % 23
=16
加法也是相同的规律
那么观察一下
我们发现——只要在计算的过程中,一旦超过求余的除数,就可以进行一次求余
而且 在没超过的求余的除数之前,求余等于它本身
那这不就直接for
循环
如以上栗子,可用如下代码执行
int m = 1;
for(int i = 1; i <= 15; ++i) {
m = m * 2;
m = m % 23;
}
输出结果
16
充分了解了同余定理之后
这道题就没问题了
等等,还记得我在上一题写的阶乘求和的快速算法吗
(不会吧,不会吧,不会有人没看完吧(doge) )
华师 PTA 2020程序设计基础实验作业题目集 编程题 #12 AC
如果每一次从1开始求阶乘,再求和,那就会超时
加上输入输出
完整代码如下
#include<iostream>
using namespace std;
int f2(int x){
long int sum = 0,mun = 1;
//这个的声明用long int,long不能省略(亲测),计算中间值会超过int的存储范围
for(int i = 1;i <= x ; ++i){
mun = (mun * i) % 1000000007;
sum = (sum + mun) % 1000000007;
}
sum = sum %1000000007;
return sum;
}
int main(){
int inp;
cin >> inp;
cout << f2(inp) << endl;
cin >> inp;
cout << f2(inp) << endl;
cin >> inp;
cout << f2(inp) << endl;
}
提交结果如下
2020年12月3日更新----------------------------------------------------------------
上述完整代码只有3次输入,而题目没有说明只有3次
所以有些取巧了
对于一般情况代码如下
#include<iostream>
using namespace std;
int f2(int x){
long int sum = 0,mun = 1;
//这个的声明用long int,long不能省略(亲测),计算中间值会超过int的存储范围
for(int i = 1;i <= x ; ++i){
mun = (mun * i) % 1000000007;
sum = (sum + mun) % 1000000007;
}
sum = sum %1000000007;
return sum;
}
int main() {
int inp;
while(cin >> inp) {
cout << f2(inp) << endl;
}
return 0;
}
欢迎dalao们指正