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\)最优解
时间计算:我们假设每次分治刚好使左右乘积位数相等,则时间为:\(O(nlog^2n)\)
\begin{array}{rcl}
2T(\frac{n}{2})+nlogn&& {1<n}\\
1&& {n=1}
\end{array} \right. \]
\(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<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('\n');
}
return 0;
}
\(Ex\)版
#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;
const double ln10=log(10);
double g(double x){return (x*log(x)-x)/ln10;}
Array answer(int l,int r){
if(l==r)return change(l);
int mid;
double al=(g(l)+g(r))/2,tl=l,tr=r,am;
while(tl+0.5<=tr){
am=(tl+tr)/2;
if(g(am)<=al)mid=am,tl=am;
else tr=am;
}
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('\n');
}
return 0;
}
N!(hdu1042)的更多相关文章
- HDU1042(N!)题解
HDU1042(N!)题解 以防万一,题目原文和链接均附在文末.那么先是题目分析: [一句话题意] 计算N的阶乘并输出. [题目分析] 题给范围上限是10000,那么毫无疑问是大数题.之前我整理过各种 ...
- ACM训练计划建议(转)
ACM训练计划建议 From:freecode# Date:2015/5/20 前言: 老师要我们整理一份训练计划给下一届的学弟学妹们,整理出来了,费了不少笔墨,就也将它放到博客园上供大家参考. 菜 ...
- Angular2入门系列教程7-HTTP(一)-使用Angular2自带的http进行网络请求
上一篇:Angular2入门系列教程6-路由(二)-使用多层级路由并在在路由中传递复杂参数 感觉这篇不是很好写,因为涉及到网络请求,如果采用真实的网络请求,这个例子大家拿到手估计还要自己写一个web ...
- Angular2学习笔记(1)
Angular2学习笔记(1) 1. 写在前面 之前基于Electron写过一个Markdown编辑器.就其功能而言,主要功能已经实现,一些小的不影响使用的功能由于时间关系还没有完成:但就代码而言,之 ...
- ASP.NET Core 之 Identity 入门(一)
前言 在 ASP.NET Core 中,仍然沿用了 ASP.NET里面的 Identity 组件库,负责对用户的身份进行认证,总体来说的话,没有MVC 5 里面那么复杂,因为在MVC 5里面引入了OW ...
- ABP入门系列(1)——学习Abp框架之实操演练
作为.Net工地搬砖长工一名,一直致力于挖坑(Bug)填坑(Debug),但技术却不见长进.也曾热情于新技术的学习,憧憬过成为技术大拿.从前端到后端,从bootstrap到javascript,从py ...
- Online Judge(OJ)搭建(第一版)
搭建 OJ 需要的知识(重要性排序): Java SE(Basic Knowledge, String, FileWriter, JavaCompiler, URLClassLoader, Secur ...
- 如何一步一步用DDD设计一个电商网站(九)—— 小心陷入值对象持久化的坑
阅读目录 前言 场景1的思考 场景2的思考 避坑方式 实践 结语 一.前言 在上一篇中(如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成),有一行注释的代码: public interfa ...
- 如何一步一步用DDD设计一个电商网站(八)—— 会员价的集成
阅读目录 前言 建模 实现 结语 一.前言 前面几篇已经实现了一个基本的购买+售价计算的过程,这次再让售价丰满一些,增加一个会员价的概念.会员价在现在的主流电商中,是一个不大常见的模式,其带来的问题是 ...
随机推荐
- 使用Vuejs 开发chrome 插件的注意事项
chrome 插件的开发其实并不难,web开发者可以使用 html, css, javascript 轻松的开发实用的 chrome 插件. 一个好的 chrome 插件可以提高我们的开发效率,甚至方 ...
- yolov3和ssd的区别
版权声明:本文为博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明. 本文链接:https://blog.csdn.net/BlowfishKing/article/d ...
- 并发编程-epoll模型的探索与实践
前言 我们知道nginx的效率非常高,能处理上万级的并发,其之所以高效离不开epoll的支持, epoll是什么呢?,epoll是IO模型中的一种,属于多路复用IO模型; 到这里你应该想到了,sele ...
- Python爬取猪肉价格网并获取Json数据
场景 猪肉价格网站: http://zhujia.zhuwang.cc/ 注: 博客: https://blog.csdn.net/badao_liumang_qizhi 关注公众号 霸道的程序猿 获 ...
- C#窗体间常用的几种传值方式、以及委托与事件的详细介绍
窗体间的传值,最好使用委托方式传值,开始之前,我们先来说一下委托与事件的关系. 委托:是一个类. 事件:是委托类型的一个特殊实例,只能在类的内部触发执行. 首先创建2个窗体,这里我们以form1为发送 ...
- js中for循环的研究
转自:http://blog.csdn.net/lushuaiyin/article/details/8541500 <html> <body> <b><ce ...
- 教你如何添加Xcode 9.3配置包?(安装流程可供其他版本安装参考)
1.准备好你想要的Xcode版本的安装包 ,这里以Xcode 9.3为例. → 2.打开Xcode开发工具的安装路径 ...
- Android开发总体布局
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android=&quo ...
- Docker安装并运行mysql5.6数据库
1.在/home目录下新建mysql目录 mysql目录中新建三个目录:conf目录.logs目录.data目录,建这些目录的目的是用来挂载docker中的mysql下的目录的. 结果如下: 1.1. ...
- JavaScript—图片与base64编码互相转换
图片转换为base64编码 <input type = "file" id = "file" onchange="popFileName(thi ...