BZOJ4402 : Claris的剑

考虑给定每个数字的个数,构造出这个序列:

肯定是1 2 1 2 3 2 3 2 3 4 3 4 ... 最大值,

或者1 2 1 2 3 2 3 2 3 4 3 4 ... 最大值 最大值-1。

本质不同的情况只有这两种,且互相不交。

设最大值为$m$,那么$1$到$m$都要有$1$个,剩下的数每多一个$i$,就要多一个$i+1$。

剩下的数假设有$t$个,那么对于每种情况,等价于$\lfloor\frac{t}{2}\rfloor$个相同的球放入$m$个不同的盒子里,允许空盒的方案数,即$C(\lfloor\frac{t}{2}\rfloor+m,m)$。

枚举最大值后累加贡献即可,注意特判最大值为$1$的情况。

时间复杂度$O(n+m)$。

 

#include<cstdio>
const int N=2000010,P=1000000007;
int n,m,i,f[N],r[N],ans;
inline int cal(int x,int y){
  if(x<0)return 0;
  x>>=1;
  if(x==0)return 1;
  return 1LL*f[x+y]*r[x]%P*r[y]%P;
}
int main(){
  scanf("%d%d",&n,&m);
  for(f[0]=f[1]=r[0]=r[1]=1,i=2;i<=n;i++){
    f[i]=1LL*f[i-1]*i%P;
    r[i]=-1LL*r[P%i]*(P/i)%P;
    while(r[i]<0)r[i]+=P;
  }
  for(i=2;i<=n;i++)r[i]=1LL*r[i]*r[i-1]%P;
  if(n&&m)ans=1;
  for(i=2;i<=m;i++){
    (ans+=cal(n-i,i-1))%=P;
    (ans+=cal(n-i-1,i-1))%=P;
  }
  return printf("%d",ans),0;
}

  

posted @ 2016-01-21 23:02  Claris  阅读(1247)  评论(0编辑  收藏  举报