一道题3

$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\n",f[lb]);
38     return 0;
39 }
View Code

 

posted @ 2018-03-20 08:41  Blue233333  阅读(191)  评论(0编辑  收藏  举报