### 4737: 組合數問題 lucas定理+數位DP

Description

C(n,m)=n!/m!*(n?m)!

## 代碼：

#include<bits/stdc++.h>
using namespace std;
#define LL long long
#define pa pair<int,int>
const int Maxn=110;
const LL mod=1000000007LL,inv=500000004LL;
{
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*f;
}
LL n,m,a[70],b[70],la,lb;
LL f[70][2][2];
//位數 是否小於n 是否小於m
LL sum(LL l,LL r){l%=mod;r%=mod;return (l+r)%mod*((r-l+1LL)%mod)%mod*inv%mod;}
int main()
{
while(T--)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
memset(f,0,sizeof(f));
if(m>n)m=n;
LL t,ans;
if(n==m)ans=sum(1,n+1);
else ans=(sum(1,m+1)+(n-m)%mod*((m+1)%mod)%mod)%mod;
t=n;
while(t)a[++la]=t%k,t/=k;
for(int i=1;i<=(la>>1);i++)swap(a[i],a[la-i+1]);
t=m;
while(t)b[++lb]=t%k,t/=k;
for(int i=1;i<=(lb>>1);i++)swap(b[i],b[lb-i+1]);
int len=max(la,lb);
if(la!=len)for(int i=la;i;i--)a[i+len-la]=a[i],a[i]=0;
if(lb!=len)for(int i=lb;i;i--)b[i+len-lb]=b[i],b[i]=0;
f[0][0][0]=1;
for(int i=0;i<len;i++)
for(int pn=0;pn<2;pn++)
for(int pm=0;pm<2;pm++)
if(f[i][pn][pm])
{
LL t=f[i][pn][pm];
if(pn&&pm)f[i+1][1][1]=(f[i+1][1][1]+t*sum(1,k)%mod)%mod;
if(pn&&!pm)
{
f[i+1][1][1]=(f[i+1][1][1]+t*(sum(1,b[i+1])+(k-b[i+1])*b[i+1]%mod)%mod)%mod;
f[i+1][1][0]=(f[i+1][1][0]+t*(k-b[i+1])%mod)%mod;
}
if(!pn&&pm)
{
f[i+1][1][1]=(f[i+1][1][1]+t*sum(1,a[i+1])%mod)%mod;
f[i+1][0][1]=(f[i+1][0][1]+t*(a[i+1]+1)%mod)%mod;
}
if(!pn&&!pm)
{
if(a[i+1]&&b[i+1])
{
if(a[i+1]<=b[i+1])f[i+1][1][1]=(f[i+1][1][1]+t*sum(1,a[i+1])%mod)%mod;
else f[i+1][1][1]=(f[i+1][1][1]+t*(sum(1,b[i+1])+(a[i+1]-b[i+1])*b[i+1]%mod)%mod)%mod;
}
if(b[i+1])f[i+1][0][1]=(f[i+1][0][1]+t*min(a[i+1]+1,b[i+1])%mod)%mod;
if(a[i+1]&&a[i+1]-1>=b[i+1])f[i+1][1][0]=(f[i+1][1][0]+t*(a[i+1]-b[i+1])%mod)%mod;
if(a[i+1]>=b[i+1])f[i+1][0][0]=(f[i+1][0][0]+t)%mod;
}
}
for(int i=0;i<2;i++)
for(int j=0;j<2;j++)
ans=((ans-f[len][i][j])%mod+mod)%mod;
printf("%lld\n",ans);
}
}