N!(hdu1042)
Posted sydevil
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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
3Sample 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)最优解
(mathfrak{Talk is cheap,show you the code.})
#include<cstdio>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
# define read read1<int>()
# define Type template<typename T>
Type inline T read1(){
T n=0;
char k;
bool fl=0;
do (k=getchar())=='-'&&(fl=1);while('9'<k||k<'0');
while(47<k&&k<58)n=(n<<3)+(n<<1)+(k^48),k=getchar();
return fl?-n:n;
}
# define f(i,l,r) for(int i=(l);i<=(r);++i)
# define fre(k) freopen(k".in","r",stdin);freopen(k".ans","w",stdout)
const double PI=acos(-1);
class complex{
public:
double x,y;
complex(){x=y=0;}
complex(double _x,double _y):x(_x),y(_y){}
complex operator * (complex b){return complex(x*b.x-y*b.y,x*b.y+y*b.x);}
complex operator + (complex b){return complex(x+b.x,y+b.y);}
complex operator - (complex b){return complex(x-b.x,y-b.y);}
complex operator * (double u){return complex(x*u,y*u);}
complex& operator *= (complex b){return *this=*this*b;}
complex& operator += (complex b){return *this=*this+b;}
complex& operator -= (complex b){return *this=*this-b;}
};
# define int long long
class Array{
private:
vector<int>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<complex>&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)<<L-1);
if(i<r[i])swap(a[i],a[r[i]]);
}
}
for(int i=1;i<len;i<<=1){
complex T(cos(PI/i),Ty*sin(PI/i));
for(int W=i<<1,j=0;j<len;j+=W){
complex n(1,0);
for(int k=0;k<i;++k,n*=T){
complex x(a[j+k]),y(n*a[i+j+k]);
a[j+k]=x+y;
a[i+j+k]=x-y;
}
}
}
}
Array operator * (Array x,Array y){
int n=x.size()-1,m=y.size()-1;
int limit=1;
while(limit<=n+m)limit<<=1;
vector<complex>_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<x.size();++i){
tem+=x[i];
x[i]=tem%100000;
tem/=100000;
}
while(tem)x.push(tem%100000),tem/=100000;
return x;
}
# undef int
Array tem;
Array answer(int l,int r){
if(l==r)return change(l);
int mid=(l+2*r)/3;
return carry(answer(l,mid)*answer(mid+1,r));
}
int main(){
int op;
while(~scanf("%d",&op)){
if(op==0){puts("1");continue;}
tem=answer(1,op);
for(int i=tem.size();~--i;)
if(i+1==tem.size())printf("%lld",tem[i]);
else printf("%05lld",tem[i]);
putchar('
');
}
return 0;
}
以上是关于N!(hdu1042)的主要内容,如果未能解决你的问题,请参考以下文章