ACM--阶乘运行时间超时

Never妥协 2020-01-17 09:51:42
怎么在求一个比较大的阶乘时,比较有效率,,比如下面这段程序
,题目在提交的时候可能在验证的时候给了一个比较大的数,显示运行时间超时了,这个程序要怎么改呢
#include<iostream>
using namespace std;
long int fun(long int);
int main()
{
int number;
int n[1000];
int i;
long int S;
cin>>number;
for(i=0;i<number;i++)
{
cin>>n[i];
}

for(i=0;i<number;i++)
{
S=0;
long int j;
for(j=1;j<n[i];j++)
{
S+=j*fun(j);
}
cout<<S%n[i]<<endl;
}
return 0;
}
long int fun(long int k)
{
long int f;
if(k==0||k==1)
{
f=1;
}
else
f=fun(k-1)*k;
return f;
}
...全文
738 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
一星伴月 2020-01-20
  • 打赏
  • 举报
回复
答案就是输入的数减一,给你解决了哈,不能直接算
  • 打赏
  • 举报
回复
你一时想不通慢慢想,还是那句话,只要你的变量容得下即可。


引用 12 楼 Never妥协 的回复:
[quote=引用 11 楼 智者知已应修善业 的回复:]
有何疑问?只要能接受得下当然可以,那你用虾米类型整数变量接受几百位甚至千位的数?
[quote=引用 10 楼 Never妥协 的回复:]
[quote=引用 8 楼 智者知已应修善业 的回复:]
不过我觉得这个程序有优化的地方,否则的话嵌套循环都要进行5000次有点影响速度,得闲优化一下。
分析阶层24*5就知道进阶是如何放到数组后面的了:4*5=20%=0,20/10=2,2*5+2=12%10=2,12/10=1,0*5+1=1%=1,1/10=0因此数组存放了120这个值。
这个最后可以把数组里存的值赋给一个整数吗?
[/quote][/quote]那个最后如果要用到这个算出来的阶乘数计算别的,那不就得把他赋给一个整型数吗[/quote]
Never妥协 2020-01-18
  • 打赏
  • 举报
回复
引用 11 楼 智者知已应修善业 的回复:
有何疑问?只要能接受得下当然可以,那你用虾米类型整数变量接受几百位甚至千位的数? [quote=引用 10 楼 Never妥协 的回复:] [quote=引用 8 楼 智者知已应修善业 的回复:] 不过我觉得这个程序有优化的地方,否则的话嵌套循环都要进行5000次有点影响速度,得闲优化一下。 分析阶层24*5就知道进阶是如何放到数组后面的了:4*5=20%=0,20/10=2,2*5+2=12%10=2,12/10=1,0*5+1=1%=1,1/10=0因此数组存放了120这个值。
这个最后可以把数组里存的值赋给一个整数吗? [/quote][/quote]那个最后如果要用到这个算出来的阶乘数计算别的,那不就得把他赋给一个整型数吗
  • 打赏
  • 举报
回复
有何疑问?只要能接受得下当然可以,那你用虾米类型整数变量接受几百位甚至千位的数?
引用 10 楼 Never妥协 的回复:
[quote=引用 8 楼 智者知已应修善业 的回复:]
不过我觉得这个程序有优化的地方,否则的话嵌套循环都要进行5000次有点影响速度,得闲优化一下。
分析阶层24*5就知道进阶是如何放到数组后面的了:4*5=20%=0,20/10=2,2*5+2=12%10=2,12/10=1,0*5+1=1%=1,1/10=0因此数组存放了120这个值。
这个最后可以把数组里存的值赋给一个整数吗?
[/quote]
Never妥协 2020-01-18
  • 打赏
  • 举报
回复
引用 8 楼 智者知已应修善业 的回复:
不过我觉得这个程序有优化的地方,否则的话嵌套循环都要进行5000次有点影响速度,得闲优化一下。 分析阶层24*5就知道进阶是如何放到数组后面的了:4*5=20%=0,20/10=2,2*5+2=12%10=2,12/10=1,0*5+1=1%=1,1/10=0因此数组存放了120这个值。
这个最后可以把数组里存的值赋给一个整数吗?
寻开心 2020-01-18
  • 打赏
  • 举报
回复
j*fun(j) 这个结果预先存到数组里面,一次完成
后面主函数里面 S+= 这个数组元素就好了

楼主直接把大家都领坑里去了,找阶乘快速算法
寻开心 2020-01-18
  • 打赏
  • 举报
回复
看楼主的代码, 似乎循环读入一个大数组,对数组每一个元素求阶乘后求和
这样的话,完全可以把这些阶乘数值一次算完,保存到一个数组当中,直接查表使用结果就好了,无需每次重新计算阶乘

提交结果是超时不是溢出, 所以改变算法是必然的选择。
寻开心 2020-01-18
  • 打赏
  • 举报
回复
又看一下楼主的描述,问题在超时上,而不是溢出上
long int在windows下也是32位, long long int 是64位
linux下long int 是64位或者32位,看cpu类型了
但是, 即便是64位的int, 算阶乘21!就溢出了
21次的迭代和递推或者递归,有差异吗?!!

问题超时归结在这个上面总觉得不太合理。 原始问题是什么,楼主最好也贴出来看看
真相重于对错 2020-01-17
  • 打赏
  • 举报
回复
引用 4 楼 Never妥协 的回复:
引用 1 楼 真相重于对错 的回复:
用迭代,不要用递归
迭代试了,也一样的
百度阶乘高效算法
Never妥协 2020-01-17
  • 打赏
  • 举报
回复
引用 1 楼 真相重于对错 的回复:
用迭代,不要用递归
迭代试了,也一样的
  • 打赏
  • 举报
回复
引用

#include<stdio.h>
#define N 5000//modify it to hold larger number
//to avoid stack overflow, define it as global varible
int f[N];//do not need to be assigned as 0 because it has already been assigned 0 by the system
int main()
{
    int n,i,j,s,up;
    scanf("%d",&n);
    for(i=2,f[0]=1;i<=n;i++)
    {
        for(j=up=0;j<N;j++)
        {
            s=f[j]*i+up;
            f[j]=s%10;
            up=s/10;
        }
    }
    for(i=N-1;f[i]==0;i--);
    for(;i>=0;i--)
    printf("%d",f[i]);
    printf("\n");
    return 0;
}
yshuise 2020-01-17
  • 打赏
  • 举报
回复
调用函数,把默认栈值扩大
真相重于对错 2020-01-17
  • 打赏
  • 举报
回复
用迭代,不要用递归
寻开心 2020-01-17
  • 打赏
  • 举报
回复
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <time.h>

#define MAX 5000
int facts[MAX];
int factd(int n) {
if ( 0==n || 1==n ) {
facts[0] = 1;
return 1;
}
memset(facts, 0, MAX*sizeof(int));
facts[0] = 1; int len = 1;
for (int i=2; i<=n; i++) {
int extend = 0;
long long int d;
for ( int j=0; j<len; j++) {
long long int a = facts[j];
d = a * i + extend;
if ( d > 1000000000) {
facts[j] = d % 1000000000;
extend = d / 1000000000;
} else
facts[j] = d, extend=0;
}
if ( extend>0) {
facts[len] = extend;
len ++;
extend = 0;
}
}
return len;
}

#include <time.h>
int main() {
clock_t start,end;
int len = 0;
start = clock();
len = factd(10000);
end = clock();
printf("len:%d\n", len);
if (len>1) {
printf("%d ", facts[len-1]);
for ( int i=len-2; i>=0; i--)
printf("%09d ", facts[i]);
} else
printf("%d", facts[0]);
double endtime=(double)(end-start)/CLOCKS_PER_SEC;
printf("time:%lf(s)", endtime);
return 0;
}
10000! 0.1s也算出来了。 输出函数用的时间长
  • 打赏
  • 举报
回复
不过我觉得这个程序有优化的地方,否则的话嵌套循环都要进行5000次有点影响速度,得闲优化一下。
分析阶层24*5就知道进阶是如何放到数组后面的了:4*5=20%=0,20/10=2,2*5+2=12%10=2,12/10=1,0*5+1=1%=1,1/10=0因此数组存放了120这个值。
  • 打赏
  • 举报
回复
我略分析了一下这个程序的原理,大概算到4和5,他没虾米算法,与普通乘法一样,就是位数进阶到数组的后面了,因此,最后的结果要倒序输出,不过其思路是值得借鉴的。
倒着存放数据,倒着输出,不过C++数组容量不会很大,因为之前写过字符串四则运算,因此,对于C++数组运算没虾米兴趣再去写,这里备录只是为了看看别人的思路而已。
Never妥协 2020-01-17
  • 打赏
  • 举报
回复
引用 3 楼 智者知已应修善业 的回复:
引用

#include<stdio.h>
#define N 5000//modify it to hold larger number
//to avoid stack overflow, define it as global varible
int f[N];//do not need to be assigned as 0 because it has already been assigned 0 by the system
int main()
{
    int n,i,j,s,up;
    scanf("%d",&n);
    for(i=2,f[0]=1;i<=n;i++)
    {
        for(j=up=0;j<N;j++)
        {
            s=f[j]*i+up;
            f[j]=s%10;
            up=s/10;
        }
    }
    for(i=N-1;f[i]==0;i--);
    for(;i>=0;i--)
    printf("%d",f[i]);
    printf("\n");
    return 0;
}
大佬,能说下原理不

64,663

社区成员

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

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