BZOJ 4402:Clarisの剣
6550 ワード
その本質によって,この方法の構造が繰り返されず,よくなるように構造方法を作ることができる.
最大の数をTとすると(n-T)の余分が必要になるので(n-T)>>1に相当してT個の箱に入れて空き箱に注意してもいいです
では、C(⌊t 2⌋+T,T)に貢献します.ここには、階乗逆元を求める小さなテクニックがあります.まずNを求めます.の逆元では(N−1)!の逆元でいいO(1)計算
最大の数をTとすると(n-T)の余分が必要になるので(n-T)>>1に相当してT個の箱に入れて空き箱に注意してもいいです
では、C(⌊t 2⌋+T,T)に貢献します.ここには、階乗逆元を求める小さなテクニックがあります.まずNを求めます.の逆元では(N−1)!の逆元でいいO(1)計算
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const
int Mod=1000000007;
int fact[2000001],fact_[20000001];
inline int Cal(int x,int y)
{
if(x<0)return 0;
x>>=1;
if(x==0)return 1;
return fact[x+y]*1ll*fact_[x]%Mod*fact_[y]%Mod;
}
int Max=2000000;
int f(int x,int y)
{
if(y==1)return x;
int t=f(x,y>>1);
if(y&1)return t*1ll*t%Mod*1ll*x%Mod;
else return t*1ll*t%Mod;
}
int ff(int x,int y)
{
int base=1,res=1,M=x;
while(y)
{
if(y&base)
y^=base,res=res*1ll*M%Mod;
base<<=1;
M=M*1ll*M%Mod;
}
return res;
}
char c;
inline void read(int &a)
{
a=0;do c=getchar();while(c<'0'||c>'9');
while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
}
int main()
{
int i,j,k;
int n,m;
read(n),read(m);
fact[1]=1;
Max=min(Max,max(n,m)+4);
for(i=2;i<=Max;i++)
fact[i]=fact[i-1]*1ll*i%Mod;
fact_[Max]=ff(fact[Max],Mod-2);
for(int i=Max-1;i;i--)
fact_[i]=fact_[i+1]*(i+1ll)%Mod;
int ans=0;
if(n&&m)ans=1;
for(i=2;i<=m;i++){(ans+=Cal(n-i,i-1))%=Mod;(ans+=Cal(n-i-1,i-1))%=Mod; }
printf("%d
",ans);
return 0;
}