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 }

 

  

posted @ 2016-05-03 21:58  邀月独斟  阅读(569)  评论(0编辑  收藏  举报