九度oj1076N的阶乘

关于这个题:LRJ的书上有一种解法,于是我就原封不动的把那代码搬上去了,试试能不能AC,果然,超时了。

只好想改进的方法,我的方法大概是这样的:LRJ那段代码当中的核心主要是

1.那2个for loop模拟N!

2.从数组最后一个元素查到第一个不为0的元素就break;

在1里面,不管是2!还是900!里边的for统统都要从0更新到maxn-1,这样明显是低效率的。

用一个数flag控制每次要更新的范围,数小的时候就从0更新到对应的flag就好了。这样,1里面改进了。

在2里面,由于有了1的基础,比如一个数很小的时候,就可以不必从最后一个元素开始查找了,而可以从flag开始往前面查找了。这样,2改进了。

代码如下,我测试了几种flag的步长,步长为3的时候AC(和你对步长的定义也有关系,不绝对),为2的时候WA,主要原因应该是:比如1000!假设带了2000多个0,而步长为2的话每次只加2,并且加到最后可能还不够1000!应该有的位数。为此,我用2.5步长(i 变 2 次flag加 5)WA,用8/3步长(i 变 3 次就加 8)AC了。虽然麻烦,还是解决了。

代码如下,有步长为3和步长为8/3两种版本。。。

#include<iostream>
using namespace std;
#include<cstring>
#define maxn 4000
 
int a[maxn];
 
int main()
{
    int inc,flag;
    int n,s;
    int i,j,k;
 
    while(cin>>n)
    {
        memset(a,0,sizeof(a));
        a[0]=1;
        flag=0;
 
        for(i = 2; i <= n; i++)
        {      
            inc=0;
 
            if((flag+3) < maxn)
                flag += 3;
                     
            for(j = 0; j < flag; j++)
                {
                    s = a[j]*i + inc;
                    a[j] = s%10;
                    inc = s/10;
                }
        }
 
        for(k = flag ; k >= 0; k--)
            if(a[k])
                break;
 
        for(int r = k; r >= 0; r--)
            cout << a[r];
        cout << "\n";
    }
    return 0;
}
/**************************************************************
    Problem: 1076
    User: true14fans
    Language: C++
    Result: Accepted
    Time:1740 ms
    Memory:1536 kb
****************************************************************/


 

#include<iostream>
using namespace std;
#include<cstring>
#define maxn 3000
 
int a[maxn];
 
int main()
{
    int inc,flag;
    int n,s;
    int i,j,k;
 
    while(cin>>n)
    {
        memset(a,0,sizeof(a));
        a[0]=1;
        flag=0;
 
        for(i = 2; i <= n; i++)
        {      
            inc=0;
 
            if((flag+8) < maxn && (i+1)%3 == 0)
                flag += 8;
                     
            for(j = 0; j <= flag; j++)
                {
                    s = a[j]*i + inc;
                    a[j] = s%10;
                    inc = s/10;
                }
        }
 
        for(k = flag ; k >= 0; k--)
            if(a[k])
                break;
 
        for(int r = k; r >= 0; r--)
            cout << a[r];
        cout << "\n";
    }
    return 0;
}
/**************************************************************
    Problem: 1076
    User: true14fans
    Language: C++
    Result: Accepted
    Time:1400 ms
    Memory:1532 kb
****************************************************************/


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值