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; }