(0! + 1! + 2! + 3! + 4! + ... + n!)%m.问题

标哥-iOS攻城狮 2012-10-01 01:21:04
0 <= n < 10^100 (without leading zero)
0 < m < 1000000

这道题有什么定理可以简化?求思路
...全文
428 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
line_us 2012-10-02
  • 打赏
  • 举报
回复
数学题有趣味
GERUIOP 2012-10-02
  • 打赏
  • 举报
回复
C语言的魅力,用自己想出来的思路来发现自己的错误和不足的同时也能学到东西。
  • 打赏
  • 举报
回复
s = 1 % m + ((i % m) * (s % m)) % m;考虑到(i * s) % m == ((i % m) * (s % m)) % m;
这么改之后,不会出现溢出。
而原来s = (1+i*s)%m这个在计算i * s的时候,由于i最大可以为10e100 - 1,而s最大可以是m-1,所以
计算时会出错,出现溢出情况。
感谢Ryan的热情帮助,我总算明白这些细节了!
  • 打赏
  • 举报
回复
//***********************************************************
//cout << "n = " << n << endl;
long long s = 1;
for (i = n; i >= 1; i--)
{
//s = (1 + i * s) % m;
s = 1 % m + ((i % m) * (s % m)) % m;
s %= m;
}
s %= m;
cout << s << endl;
}
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 的回复:]

引用 16 楼 的回复:
引用 15 楼 的回复:

引用 14 楼 的回复:
引用 9 楼 的回复:

n>=m的时候n!%m==0。所以只要O(m)就可以了
C/C++ code

//用 秦九昭乘法

//【用a*~b表示 从a乘到b】

(0! + 1! + 2! + 3! + 4! + ... + n!)
=1+(1*~1 + 1*~2 + 1*~3 + ……
[/Quote]

我后来想了想,可能是中间存储S的值的时候会溢出,所以我改成这样,现在就过了!
非常感谢Ryan这位积极帮助他人解决问题的朋友。我改的代码如下,

//***********************************************************
//cout << "n = " << n << endl;
long long s = 1;
for (i = n; i >= 1; i--)
{
//s = (1 + i * s) % m;
s = 1 % m + ((i % m) * (s % m)) % m;
s %= m;
}
s %= m;
cout << s << endl;
}
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 的回复:]

引用 14 楼 的回复:
引用 9 楼 的回复:

n>=m的时候n!%m==0。所以只要O(m)就可以了
C/C++ code

//用 秦九昭乘法

//【用a*~b表示 从a乘到b】

(0! + 1! + 2! + 3! + 4! + ... + n!)
=1+(1*~1 + 1*~2 + 1*~3 + 1*~4 + ... + 1*~n)【0的阶乘单独处理】
……
[/Quote]
还是不通过,不知道是什么原因
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 的回复:]

n>=m的时候n!%m==0。所以只要O(m)就可以了
C/C++ code

//用 秦九昭乘法

//【用a*~b表示 从a乘到b】

(0! + 1! + 2! + 3! + 4! + ... + n!)
=1+(1*~1 + 1*~2 + 1*~3 + 1*~4 + ... + 1*~n)【0的阶乘单独处理】
=1+ 1*(1 + 2*~2 + 2*~3+2*~4+ ... +2*……
[/Quote]

谢谢您提供的方法,我采用你的第一种方法试了一下,测试我的数据都是对的,不过提交就是wrong answer
您提价的第二种方法是我上面已经贴出来的代码的方法,
这两种方法都不能够得出正确的结果,我把代码放出来,请您看看是不是我哪里弄错了!
#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;

#define MAX_LEN 1000001
int main()
{
long m;
long n = 0;
char ch[MAX_LEN];
int testNum, i;

cin >> testNum;
for (int test = 1; test <= testNum; test++)
{
scanf("%s %ld", ch, &m);
//***************确定n的值*********************************
for (i = 0; ch[i] != '\0'; i++)
;
int len = i;

//cout << "ch =" << ch << endl;
// cout << "len = " << len << endl;
if (len >= 7)
{
n = m-1;
}
else
{
int k = 1;
n = ch[len-1]-'0';
for (int j = len-2; j >= 0; --j)
{
n += (ch[j] - '0') * pow(10, k);
k ++;
if (n >= m)
{
n = m-1;
break;
}
}
}
//***********************************************************
cout << "n = " << n << endl;
long s = 1;
for (i = n; i >= 1; i--)
{
s = (1 + i * s) % m;
s %= m;
}
s %= m;
cout << s << endl;
}

return 0;
}
csdn一绝 2012-10-01
  • 打赏
  • 举报
回复
OI是什么?不懂,我只知道这是个数学题[Quote=引用 12 楼 的回复:]
引用 11 楼 的回复:
从题目分析看 这道题首先有两个不确定的参数 n 和 m ,而且两者都有个数值范围,n的数值范围[0,10的100次方),m的值范围(0,1000000), 计算机的最长的long double 数据类型的范围不够存n ,所以不可能达到10的100次方,而且分析得出题目所求结果值必然在(1,999998]范围的数值,
给一个方案做个循环for( i = 1, i < 计……
[/Quote]
csdn一绝 2012-10-01
  • 打赏
  • 举报
回复
从题目分析看 这道题首先有两个不确定的参数 n 和 m ,而且两者都有个数值范围,n的数值范围[0,10的100次方),m的值范围(0,1000000), 计算机的最长的long double 数据类型的范围不够存n ,所以不可能达到10的100次方,而且分析得出题目所求结果值必然在(1,999998]范围的数值,
给一个方案做个循环for( i = 1, i < 计算机能存的数的最大范围的值,i++) 将n范围值的所有的结果计算出来,存放到记事本中,你自己可以观察,这个结果肯定跟数m有关系,而且可能磁盘不晓得能存下这结果么。
  • 打赏
  • 举报
回复
我按我的想法做了一下,测试给出的数据都通过了,不过提交结果是wrong answer,
求助!

#include <iostream>
#include <cstdio>
#include <cmath>
using namespace std;

#define MAX_LEN 1000001
int main()
{
long m;
long n = 0;
char ch[MAX_LEN];
int testNum, i;

cin >> testNum;
for (int test = 1; test <= testNum; test++)
{
scanf("%s %ld", ch, &m);
//***************确定n的值*********************************
for (i = 0; ch[i] != '\0'; i++)
;
int len = i;

// cout << "ch =" << ch << endl;
// cout << "len = " << len << endl;
if (len >= 7)
{
n = m-1;
}
else
{
int k = 1;
n = ch[len-1]-'0';
for (int j = len-2; j >= 0; --j)
{
n += (ch[j] - '0') * pow(10, k);
k ++;
if (n >= m)
{
n = m-1;
break;
}
}
}
//***********************************************************
cout << "n = " << n << endl;
long sum = 2;
long s = 1;//上一个数的余数
long t;
for (i = 2; i <= n; i++)
{
t = i * s;
s = (t % m);
sum = (s + sum) % m;
}
cout << sum << endl;
}

return 0;
}
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

不懂你的意思.
[/Quote]
那可以把你的算法写一下吗?
  • 打赏
  • 举报
回复
那您可不可以把你的算法写一下?
qq120848369 2012-10-01
  • 打赏
  • 举报
回复
不懂你的意思.
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 的回复:]

计算本身是递推的,另外加和的模可以等于模的加和,最后楼上的道理你也明白。
[/Quote]
n! % m 如果拆分出来计算呢?
又不等于 每个数分别与m求余的结果的乘积
qq120848369 2012-10-01
  • 打赏
  • 举报
回复
计算本身是递推的,另外加和的模可以等于模的加和,最后楼上的道理你也明白。
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]

n>=m的时候n!%m==0。所以只要O(m)就可以了
[/Quote]

N>=M时,余数是0,这我知道,但是当N<M时,n!%m怎么求?怎么拆分出来?
FancyMouse 2012-10-01
  • 打赏
  • 举报
回复
n>=m的时候n!%m==0。所以只要O(m)就可以了

64,682

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧