$x,y leq 1e18$,求式子$sum_{i=0}^{x}C_{frac{x+y}{2}}^{i}C_{x-i}^{frac{x+y}{2}} mod 1e5+3$。
Lucas定理的高度感性理解是把$mod p$下的每一位算组合数然后乘起来,因此可以采用一个数位DP的方式算这个式子。
然而比较头疼的是有个减号,涉及退位,因此每一位把$leq 当前位及更低位组成的数$的值和$>他$的值分开来算,退位时用上一位的$>$计算,不退位用上一位$leq$算。
代码很精髓。需反复分析。
1 //#include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #include<vector> 6 //#include<queue> 7 //#include<time.h> 8 //#include<complex> 9 #include<algorithm> 10 #include<stdlib.h> 11 using namespace std; 12 13 #define LL long long 14 LL X,Y; 15 int f[10],g[10],a[10],la=0,b[10],lb=0; 16 const int mod=1e5+3; 17 int fac[mod+4],inv[mod+4]; 18 int powmod(int a,int b) {int ans=1; while (b) {if (b&1) ans=1ll*ans*a%mod; a=1ll*a*a%mod; b>>=1;} return ans;} 19 int C(int n,int m) {return m>n?0:fac[n]*1ll*inv[m]%mod*inv[n-m]%mod;} 20 int main() 21 { 22 scanf("%lld%lld",&X,&Y); 23 if (X<Y || ((X^Y)&1)) {puts("0"); return 0;} 24 fac[0]=1; for (int i=1;i<=mod;i++) fac[i]=fac[i-1]*1ll*i%mod; 25 inv[mod-1]=powmod(fac[mod-1],mod-2); for (int i=mod-1;i;i--) inv[i-1]=inv[i]*1ll*i%mod; 26 X^=Y^=X^=Y; X=(X+Y)>>1; 27 f[0]=1; 28 LL tmp=X; while (tmp) a[++la]=tmp%mod,tmp/=mod; 29 tmp=Y; while (tmp) b[++lb]=tmp%mod,tmp/=mod; 30 for (int i=1;i<=lb;i++) 31 { 32 for (int j=0;j<mod;j++) if (b[i]>=j) f[i]=(f[i]+1ll*f[i-1]*C(a[i],j)%mod*C(b[i]-j,a[i]))%mod; 33 else g[i]=(g[i]+1ll*f[i-1]*C(a[i],j)%mod*C(b[i]+mod-j,a[i]))%mod; 34 for (int j=0;j<mod;j++) if (b[i]>=j+1) f[i]=(f[i]+1ll*g[i-1]*C(a[i],j)%mod*C(b[i]-j-1,a[i]))%mod; 35 else g[i]=(g[i]+1ll*g[i-1]*C(a[i],j)%mod*C(b[i]+mod-j-1,a[i]))%mod; 36 } 37 printf("%d ",f[lb]); 38 return 0; 39 }