N!(hdu1042)

N!

Given an integer N(0 ≤ N ≤ 10000), your task is to calculate N!

Input

One N in one line, process to the end of file.

Output

For each N, output N! in one line.

Sample Input

1

2

3

Sample Output

1

2

6

思路:

压位高精\(or FFT\),当然压位只能卡过去,\(FFT\)时需要对数列分治,即为\(\prod_{i=l}^r=(\prod_{i=l}^{mid}i)(\prod_{i=mid+1}^{r}i)\)

原因:

我们可以发现,在\(FFT\)时我们需要把\(2\)个序列强行拉高到\(2^n\)位,所以当参与乘法的\(2\)个序列(位数)越相近时\(FFT\)效率越高,所以我们把\(\frac{r!}{(l-1)!}\)拆为\(\frac{mid!}{(l-1)!}*\frac{r!}{mid!},\)一般\(mid\)\(\frac{l+r*2}{3}\)或黄金比例时最优。当然,\(FFT\)与压位共用更优,笔者取得\(hdu\)最优解

时间计算:我们假设每次分治刚好使左右乘积位数相等,则时间为:\(O(nlog^2n)\)

\[ T(n)=\left\{ \begin{array}{rcl} 2T(\frac{n}{2})+nlogn&& {1

\(Ex:如何让左右长度更接近\)

数字\(n\)的长度约为\(lg\ n(以10为底的对数函数)\)

\(\because len(\prod_{i=l}^ri)\approx \sum_{i=l}^rlg\ i\approx \int_l^rlg\ x\ dx\)

\(\therefore 我们想要\int_l^{mid}lg\ x\ dx=\int_{mid}^rlg\ x\ dx\)

\(\rightarrow \int_0^llg\ x\ dx+\int_0^rlg\ x\ dx=2\int_0^{mid}lg\ x\ dx\)

\(\because \int lg\ x\ dx=\frac{xlnx-x}{ln10}\)

\(\therefore 我们二分mid,使\frac{mid\ lnmid-mid}{ln10}=\frac{\frac{l\ lnl-l}{ln10}+\frac{r\ lnr-r}{ln10}}{2}\)

\(\mathfrak{Talk\ is\ cheap,show\ you\ the\ code.}\)

普通版

#include
#include
#include
#include
using namespace std;
# define read read1()
# define Type template
Type inline T read1(){
    T n=0;
    char k;
    bool fl=0;
    do (k=getchar())=='-'&&(fl=1);while('9'a;
    public:
        Array(){}
        void push(int n){a.push_back(n);}
        Array(int* l,int* r){while(l!=r)push(*l),++l;}
        int size(){return a.size();}
        int& operator [] (const int x){return a[x];}
};
void FFT(const int len,vector&a,const int Ty,int *r=NULL){
    if(!r){
        r=new int[len];
        r[0]=0;int L=log2(len);
        f(i,0,len-1){
            r[i]=(r[i>>1]>>1)|((i&1)<_x(limit+1),_y(limit+1);
    Array ans;
    f(i,0,n)_x[i]=complex(x[i],0);
    f(i,0,m)_y[i]=complex(y[i],0);
    FFT(limit,_x,1);
    FFT(limit,_y,1);
    f(i,0,limit)_x[i]*=_y[i];
    FFT(limit,_x,-1);
    f(i,0,n+m)ans.push((int)(_x[i].x/limit+0.5));
    return ans;
}
void into(int n,Array &x){
    f(i,0,n)x.push(read);
}
Array change(int n){
    Array tem;
    do tem.push(n%100000);while(n/=100000);
    return tem;
}
Array carry(Array x){
    int tem=0;
    for(int i=0;i

\(Ex\)

#include
#include
#include
#include
using namespace std;
# define read read1()
# define Type template
Type inline T read1(){
    T n=0;
    char k;
    bool fl=0;
    do (k=getchar())=='-'&&(fl=1);while('9'a;
    public:
        Array(){}
        void push(int n){a.push_back(n);}
        Array(int* l,int* r){while(l!=r)push(*l),++l;}
        int size(){return a.size();}
        int& operator [] (const int x){return a[x];}
};
void FFT(const int len,vector&a,const int Ty,int *r=NULL){
    if(!r){
        r=new int[len];
        r[0]=0;int L=log2(len);
        f(i,0,len-1){
            r[i]=(r[i>>1]>>1)|((i&1)<_x(limit+1),_y(limit+1);
    Array ans;
    f(i,0,n)_x[i]=complex(x[i],0);
    f(i,0,m)_y[i]=complex(y[i],0);
    FFT(limit,_x,1);
    FFT(limit,_y,1);
    f(i,0,limit)_x[i]*=_y[i];
    FFT(limit,_x,-1);
    f(i,0,n+m)ans.push((int)(_x[i].x/limit+0.5));
    return ans;
}
void into(int n,Array &x){
    f(i,0,n)x.push(read);
}
Array change(int n){
    Array tem;
    do tem.push(n%100000);while(n/=100000);
    return tem;
}
Array carry(Array x){
    int tem=0;
    for(int i=0;i

你可能感兴趣的:(N!(hdu1042))