Processing math: 20%

【Codeforces 582D】Number of Binominal Coefficients

数位 DP。

题目大意:

给定质数 p 和 整数 α,大整数 A,求有多少对 n,k 满足 0knAp^\alpha|\binom{n}{k}

题解:

我们考虑如何求 \binom{n}{m} 中含有的质因子 p 个数。

不难发现,对每个 i,它对质因子个数的贡献只可能为 01

而是否产生贡献,取决于 mn-mp 进制下做加法的第 i 位是否进位。

于是,我们先将 A 转化为 p 进制,然后进行数位 DP 即可。

f[n][m][0/1][0/1] 表示当前考虑到第 n 位,之前已经进位 m 次,前面考虑的位是否紧贴上界,最后考虑的这位是否需要从下一位进 1

然后转移分一些情况讨论即可。

最后对于进位次数大于等于 \alpha最低位不进位的方案求和即可。

时间复杂度 O(|A|^2)

Code:

  1. #include<cstdio>
  2. #include<cctype>
  3. #include<cstring>
  4. #include<algorithm>
  5. using namespace std;
  6. typedef long long LL;
  7. const int N=5005,md=1e9+7;
  8. int p,alpha,n;
  9. int A[N],ans;
  10. inline void add(int&a,const LL&b){a=(a+b)%md;}
  11. void Read(){
  12. char s[N],t[N];
  13. scanf("%s",s);
  14. int lens=strlen(s);
  15. for(int i=0;i<lens;++i)s[i]^='0';
  16. while(1){
  17. LL d=0;int lent=0;
  18. for(int i=0;i<lens;++i){
  19. d=d*10+s[i];
  20. t[lent++]=d/p,d-=d/p*p;
  21. }
  22. int beg=0;
  23. while(t[beg]==0&&beg<lent)++beg;
  24. A[n++]=d;
  25. if(lent==beg)return;
  26. for(int i=beg;i<lent;++i)
  27. s[i-beg]=t[i];
  28. lens=lent-beg;
  29. }
  30. }
  31. int f[2][N][2][2];
  32. int a1,a2,a3,a4;
  33. inline int calc(int x){
  34. if(x<p)return(x+1LL)*(x+2)/2%md;
  35. return(a1-calc(2*p-3-x)+md)%md;
  36. }
  37. void calc(){
  38. a1=(LL)p*p%md,a3=calc(p-1),a2=(a1-a3+md)%md,a4=calc(p-2);
  39. f[0][0][0][0]=calc(A[0]-1);
  40. f[0][1][0][1]=calc(A[0]-2);
  41. f[0][0][1][0]=A[0]+1;
  42. f[0][1][1][1]=A[0];
  43. for(int i=1;i<n;i++){
  44. memset(f[i&1],0,sizeof*f);
  45. for(int c=0;c<=alpha;++c){
  46. const int t=min(c+1,alpha);
  47. const int&P=f[i&1^1][c][0][0];
  48. add(f[i&1][c][0][0],(LL)P*a3);
  49. add(f[i&1][t][0][1],(LL)P*a4);
  50. const int&Q=f[i&1^1][c][0][1];
  51. add(f[i&1][c][0][0],(LL)Q*(a1-a3+md));
  52. add(f[i&1][t][0][1],(LL)Q*(a1-a4+md));
  53. const int&X=f[i&1^1][c][1][0];
  54. add(f[i&1][c][0][0],(LL)X*calc(A[i]-1));
  55. add(f[i&1][t][0][1],(LL)X*calc(A[i]-2));
  56. add(f[i&1][c][1][0],(LL)X*(A[i]+1));
  57. add(f[i&1][t][1][1],(LL)X*A[i]);
  58. const int&Y=f[i&1^1][c][1][1];
  59. add(f[i&1][c][0][0],(LL)Y*(calc(A[i]+p-1)-a3+md));
  60. add(f[i&1][t][0][1],(LL)Y*(calc(A[i]+p-2)-a4+md));
  61. add(f[i&1][c][1][0],(LL)Y*(p-A[i]-1));
  62. add(f[i&1][t][1][1],(LL)Y*(p-A[i]));
  63. }
  64. }
  65. ans=(f[n&1^1][alpha][0][0]+f[n&1^1][alpha][1][0])%md;
  66. }
  67. int main(){
  68. scanf("%d%d",&p,&alpha);
  69. if(alpha>5000)return puts("0")&0;
  70. Read();
  71. reverse(A,A+n);
  72. calc();
  73. printf("%d\n",ans);
  74. return 0;
  75. }

Gitalking ...