第一道Catalan数的题!!!题目并不难,但关键在于时间的优化!!!
一开始的时候求阶乘相除没用唯一分解式,TLE,后乃改了,但没写成函数的形式,还是TLE,没办法
开别人的代码后,改成函数,奇迹般过了!!!
#include<iostream>
#include<stdio.h>
#include<map>
#define MAXN 123456
using namespace std;
int N,kind_factor,total_factor;
map<int,int> Q;//记录每一个数的唯一分解式;第一个数素因数,第二个数为对应指数
map<int,int> p;
int factor[MAXN],t[MAXN];
int compute_factor(int *a,map<int,int>& b,int n,int d)//很牛的方法球唯一分解式
{
int k=0;
for(int i=2;i*i<=n;i++)
{
if(n%i==0)
{
a[k++]=i;
while(n%i==0)
{
b[i]+=d;
n/=i;
}
}
}
if(n>1)
{
a[k++]=n;
b[n]+=d;
}
return k;
}
long long compute_catalan(int k)
{
long long cn_1=1,cn=1;
for(int i=2;i<=k;i++)
{
cn=cn_1*2*(2*i-1)/(i+1);
cn_1=cn;
}
return cn;
}
long long compute_factorial()
{
p.clear();
for(int i=2;i<=total_factor;i++)//计算(total_factor)!用唯一分解式表示
{
compute_factor(t,p,i,1);
}
for(int i=0;i<kind_factor;i++)//计算每一个素因子个数的阶乘用唯一分解式表示
{
for(int j=2;j<=Q[factor[i]];j++)
{
compute_factor(t,p,j,-1);
}
}
map<int,int>::iterator it;
long long res=1;
for(it=p.begin();it!=p.end();it++)
{
for(int j=1;j<=(it->second);j++)
{
res*=(it->first);
}
}
return res;
}
int main()
{
while(scanf("%d",&N)==1)
{
Q.clear();
kind_factor=compute_factor(factor,Q,N,1);
total_factor=0;
for(int i=0;i<kind_factor;i++)
{
total_factor+=Q[factor[i]];
}
long long kind_tree=compute_catalan(total_factor-1);
long long temp=compute_factorial();
unsigned long long ans=1;
ans=temp*kind_tree;
printf("%llu/n",ans);
}
return 0;
}
//这个代码和上面没什么不同不知为什么就是超时!!!
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<map>
using namespace std;
long long N;
struct prim_factor
{
long long fac;
long long num;
}pf[100005];
map<int,int > Q;
int main()
{
while(scanf("%I64d",&N)!=EOF)
{
//Q.clear();
long long m=(long long)sqrt(N+0.5);
long long kind=0;//记录因子的种数!!!
long long total=0;
for(int i=2;i<=m;i++)能整除n的质数必小于等于 sqrt(x);
if(N%i==0)
{
pf[kind].fac=i;
pf[kind].num=0;
while(N%i==0)
{
N/=i;
pf[kind].num++;
total++;
}
kind++;
}
if(N>=2)
{
pf[kind].fac=N;
pf[kind].num++;
kind++;
total++;
}
//计算树的形状数catalan
int n=total-1;
long long cn=1,cn_1=1;//cn为第n个Catalan数
for(int i=2;i<=n;i++)
{
cn=cn_1*2*(2*(i-1)+1)/(i+1);
cn_1=cn;
}
//printf("%I64d/n",cn);
//printf("%I64d/n",cn);
//求total!的唯一分解试
Q.clear();
for(int i=2;i<=total;i++)
{
int u=i;
int temp0=(int)sqrt(total+0.5);
for(int j=2;j<=temp0;j++)
{
if(u%j==0)
{
while(u%j==0)
{
Q[j]++;
u/=j;
}
}
}
if(u>=2)
{
Q[u]++;
}
}
//用(total!)/n1!/n2!/.....
for(int i=0;i<kind;i++)
{
for(int j=2;j<=pf[i].num;j++)
{
int temp1=j;
int temp2=(int)sqrt(temp1+0.5);
for(int k=2;k<=temp2;k++)
{
if(temp1%k==0)
{
while(temp1%k==0)
{
Q[k]--;
temp1/=k;
}
}
}
if(temp1>1)
{
Q[temp1]--;
}
}
}
map<int,int >::iterator it;
long long ans=1;
for(it=Q.begin();it!=Q.end();it++)
{
for(int j=1;j<=(it->second);j++)
ans*=(it->first);
//printf("%I64d/n",ans);
}
ans*=cn;
printf("%I64d/n",ans);
}
return 0;
}
(暴力搜索)看来是暂时过不了了!!!TLE;
#include<string.h>
#include<stdio.h>
#include<map>
#include<math.h>
#include<iostream>
#define MAXN 7000000
using namespace std;
long long int ans[MAXN];
//map<long,bool> f;
bool f(int x){
//long y=long (sqrt(0.0+x)+1);
for(int i=2;i*i<=x;i++) if(x%i==0) return false;
return true;}
long long int dfs(int n){
long long int sum=0;
int i;
if(n<MAXN){
if(ans[n]) return ans[n];
else{
if(f(n)) return ans[n]=1;
//long r=(long)sqrt(n+0.0);
for( i=2;i*i<n;i++){
if(n%i==0) sum+=dfs(i)*dfs(n/i);}
sum*=2;
if(i*i==n) sum+=dfs(i)*dfs(i);
return ans[n]=sum;
}
}
else{
if(f(n)) return 1;
//long r=(long)sqrt(n+0.0);long i=0;
for(i=2;i*i<n;i++)
if(n%i==0) sum+=dfs(i)*dfs(n/i);
sum*=2;
if(i*i==n) sum+=dfs(i)*dfs(i);
return sum;}
}
int main(){
//freopen("in.txt","r",stdin);
//筛素数
/* long i,j;
ans[2]=1;
for(long i=2;i<=NI;i++) f[i]=1;
long s,e=(long)(sqrt(0.0+NI)+1);
f[0]=f[1]=0;
for(i=4;i<NI;i+=2) f[i]=0;
for(i=3;i<e;i+=2) if(f[i]){
for(s=i*2,j=i*i;j<NI;j+=s) f[j]=0;
}*/
memset(ans,0,sizeof(ans));
int num;
while(scanf("%d",&num)!=EOF){
if(num<MAXN&&ans[num]) printf("%I64d/n",ans[num]);
else{
printf("%I64d/n",dfs(num));}
}
return 0;}
----------------------------------------------------------------------------------------------------------------------
这个好像是一日本人写的报告,看不懂!!!