[bzoj1485] [HNOI2009]有趣的数列

  找规律题。。。

  首先观察样例解释可得。我们只要确定奇数位的情况就行了,并且只要i<=第i个奇数<=2*i-1就是合法的= =

  然后我就一直在找规律..................

  最后弃疗跑去看题解....才发现答案不就是卡特兰数吗。。为啥我看半天都没看出来= =

  由搜索引擎可得,h(n)=C(2*n,n)/(n+1)。。。求组合数的话我写了分解质因数...

  顺便学(chao)习(xi)了一下黄学长的分解质因数。。我以前写的都是什么鬼QAQ

  写了个快速幂竟然比直接乘慢orz

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstring>
 4 #define ll long long
 5 using namespace std;
 6 const int maxn=2000023;
 7 bool cant[maxn];
 8 int pri[maxn],num,mn[maxn],sum[maxn];
 9 ll ans;
10 int i,j,k,n,m,sxt;
11 inline void prerun(int x){
12     register int i,j,k;
13     for(i=2;i<=x;i++){
14         if(!cant[i])pri[++num]=i,mn[i]=num;
15         for(k=pri[j=1]*i;k<=x&&j<=num;k=pri[++j]*i){
16             cant[k]=1,mn[k]=j;
17             if(!(i%pri[j]))break;
18         }
19     }
20 }
21 inline void upd(int x,int v){
22     while(x>1)
23         sum[mn[x]]+=v,x/=pri[mn[x]];
24 }
25 inline int power(ll a,int b){
26     ll c=1;
27     while(b){
28         if(b&1){c*=a;if(c>=sxt)c%=sxt;}
29         a*=a;if(a>=sxt)a%=sxt;
30         b>>=1;
31     }
32     return c;
33 }
34 int main(){
35     scanf("%d%d",&n,&sxt);
36     prerun(n<<1);
37     for(i=n<<1;i>n;i--)upd(i,1);
38     for(;i;i--)upd(i,-1);
39     upd(n+1,-1);
40     ans=1;
41     for(i=1;i<=num;i++){
42         ans*=power(pri[i],sum[i]);
43         if(ans>=sxt)ans%=sxt;
44     }
45     printf("%lld\n",ans);
46     return 0;
47 }
View Code

其实那个合法的条件也可以变一下,将数列里的每个数都减去(i-1)之后就是1<=第i个奇数<=i 。。。就是卡特兰数了>_<

你可能感兴趣的:([bzoj1485] [HNOI2009]有趣的数列)