hdu5673 Robot 卡特兰数 / 默慈金数
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5673
分析:
这道题是一道裸的默慈金数,比较容易想到的是用卡特兰数来做。不了解的可以先学习一下。
卡特兰数:http://www.cnblogs.com/yaoyueduzhen/p/5456490.html
默慈金数:http://www.cnblogs.com/yaoyueduzhen/p/5456530.html
记路径长度为nn,那么机器人最多向右走⌊n/2⌋步并向左走⌊n/2⌋步。
Ans(n)=∑C(n,2i) Catalan(i)
其中 C(n,2i) 表示从n个物品中取2*i个的组合数,Catalan(n)表示第n个卡特兰数,0 <= i <= ⌊n/2⌋
基于n的取值范围,此题可以预处理出1,000,001以内的乘法逆元、卡特兰数。
每次询问,都可以递推组合数,或者提前一次性预处理好阶乘和阶乘的逆元得到组合数;累加组合数与相应卡特兰数的乘积,得到答案。
事实上,Ans(n)是第n个默慈金数,利用递推公式可以快速求出。
卡特兰数代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 6 using namespace std; 7 const long long mod=1000000007; 8 long long n; 9 long long ans[1100000],ni[1100000]; 10 11 long long power(long long a,long long n,long long m) 12 { 13 long long ans=1,tmp=a; 14 while(n) 15 { 16 if(n&1) 17 ans=ans*tmp%m; 18 tmp=tmp*tmp%m; 19 n=n>>1; 20 } 21 return ans%m; 22 } 23 24 void init() 25 { 26 ans[0]=1; 27 ans[1]=1; 28 for(long long i=1;i<=1000005;i++) 29 ni[i]=power(i,mod-2,mod)%mod; 30 for(long long i=2;i<=1000000;i++) 31 ans[i]=(4*i-2)%mod*ans[i-1]%mod*ni[i+1]%mod; 32 } 33 34 int main() 35 { 36 init(); 37 int T; 38 scanf("%d",&T); 39 while(T--) 40 { 41 scanf("%lld",&n); 42 long long res=0,tmp=1; 43 for(long long i=0;i*2<=n;i++) 44 { 45 res=(res+tmp*ans[i]%mod)%mod; 46 tmp=tmp*(n-2*i)%mod*(n-2*i-1)%mod*ni[2*i+1]%mod*ni[2*i+2]%mod; 47 } 48 cout<<res<<endl; 49 } 50 return 0; 51 }
默慈金数代码:
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 6 using namespace std; 7 8 const long long mod=1000000007; 9 long long n; 10 long long ans[1100000]; 11 long long power(long long a,long long n,long long m) 12 { 13 long long ans=1,tmp=a; 14 while(n) 15 { 16 if(n&1) 17 ans=ans*tmp%m; 18 tmp=tmp*tmp%m; 19 n=n>>1; 20 } 21 return ans; 22 } 23 24 int main() 25 { 26 ans[1]=1; 27 ans[2]=2; 28 for(long long i=2;i<=1000000;i++) 29 ans[i+1]=((2*i+3)%mod*ans[i]%mod+3*i*ans[i-1]%mod)%mod*power(i+3,mod-2,mod)%mod; 30 int T; 31 scanf("%d",&T); 32 while(T--) 33 { 34 scanf("%lld",&n); 35 cout<<ans[n]<<endl; 36 } 37 return 0; 38 }