关于这个题: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
****************************************************************/