Subtask1:​​​$m,nd\le 2\times 10^{3}$

对$M$质因数分解,假设$M=\prod_{i=1}^{k}p_{i}^{\alpha_{i}}$(其中$p_{i}$为素数),对每个$i$求出$f(j)\ mod\ p_{i}^{\alpha_{i}}$的值,再通过exgcd即可求出$f(j)$,注意到$\sum \log p_{i}^{\alpha_{i}}=\log M$,即exgcd的复杂度仅为$o(m\log M)$

在模$p^{\alpha}$的意义下,只需要将数值以$r\cdot p^{k}$的形式描述(其中$p\not\mid r$),即可支持求逆元

预处理$nd$以内阶乘即逆元,复杂度为$o(nd\log M)$,即可$o(1)$求出${n\choose m}mod\ p^{\alpha}$,那么暴力计算即可

时间复杂度为$o(nm\log M)$,可以通过

Subtask2:$d=1$

对于多项式$F(x)$,记$F(x)[x^{n}]$表示该多项式$n$次项系数

根据二项式定理,有${n\choose m}=(1+x)^{n}[x^{m}]$,即$f(j)=(\sum_{i=0}^{n-1}(1+x)^{id})[x^{j}]mod\ M$

记后者为$C(x)$,根据等比数列求和,即$C(x)=\frac{(1+x)^{nd}-1}{(1+x)^{d}-1}mod\ x^{m}$

由于分子和分母同时除以$x$,即分别为$\begin{cases}A(x)=\sum_{i=1}^{nd}{nd\choose i}x^{i-1}\\B(x)=\sum_{i=1}^{d}{d\choose i}x^{i-1}\end{cases}$,那么$C(x)=\frac{A(x)}{B(x)}mod\ x^{m}$

由于$d=1$,即$B(x)=1$,那么$C(x)=A(x)\ mod\ x^{m}$

考虑$A(x)[x^{i}]={nd\choose i+1}$,将$i$从小到大枚举,每次即乘上$\frac{nd-i}{i+1}$,关于如何支持除法与Subtask1相同(对$M$质因数分解并将数值以$r\cdot p^{k}$的形式描述),即可$o(m\log M)$求出$A(x)$

时间复杂度为$o(m\log M)$,可以通过

Subtask3:$m\le 8\times 10^{3}$,$M=998244353$

当$M=998244353$时,$A(x)$可以线性预处理逆元做到$o(m)$,$B(x)$多项式求逆即可

时间复杂度为$o(m \log m)$,可以通过

(由于本做法与正解关系不大,这里就不实现了)

Subtask4:$\gcd(d,M)=1$

仍考虑$C(x)=\frac{A(x)}{B(x)}mod\ x^{m}$,也即$B(x)\cdot C(x)\equiv A(x)(mod\ x^{m})$

考虑$i$次项系数,即$\forall 0\le i<m,\sum_{j=0}^{i}B(x)[x^{j}]\cdot C(x)[x^{i-j}]=A(x)[x^{i}]$

再代入具体的式子,即$\sum_{j=0}^{i}{d\choose j+1}\cdot C(x)[x^{i-j}]=A(x)[x^{i}]$

将$j\ne 0$的部分减到右边并同除以$d$,即$C(x)[x^{i}]=\frac{A(x)[x^{i}]-\sum_{j=1}^{i}{d\choose j+1}\cdot C(x)[x^{i-j}]}{d}$

$A(x)$可以$o(m\log M)$求出,而求和式在$j\ge d$时无意义,可以$o(d)$求出

由于$\gcd(d,M)=1$,也即$p\not\mid d$,可以扩欧求出$d$在模$p^{\alpha}$意义下的逆元来支持除法

时间复杂度为$o(m(d+\log M))$,可以通过

Subtask5:$d$为质数

当$p\not\mid d$时,仍用逆元的方式处理即可,以下考虑$p\mid d$的情况:

由于$d$是素数,那么$p\mid d$当且仅当$p=d$

此时,将原式变形,可得$C(x)[x^{i}]=A(x)[x^{i+d-1}]-\sum_{j=1}^{d-1}{d\choose j}C(x)[x^{i+j}]$

(虽然这个等式仅在$i+d\le m$时成立,但令其在$i$更大时成立不影响正确性)

不断迭代,即按照$i$从小到大维护当前$C(x)[x^{i}]$的系数,并将其乘上$-{d\choose j}$转移到$C(x)[x^{i+j}]$

每转移一次都会让$p$的幂次增加1,那么最多转移$\alpha$次即会在模$p^{\alpha}$意义下为0

由此,我们发现$C(x)[x^{i}]$可以被描述为关于$A(x)[x^{i+d-1}],A(x)[x^{i+d}],...,A(x)[x^{i+d\alpha}]$的一个线性的式子,在一开始迭代$o(d^{2}\alpha)$预处理出来,再利用此递推式$o(md\alpha)$计算即可

时间复杂度为$o(md\log M)$,可以通过

Subtask6:无特殊限制

仍考虑$p\not\mid d$的情况,此时前面的做法并不一定正确,原因是存在$1\le j<d$使得${d\choose j}$使得不是$p$的倍数

对于这个问题,令$t$为最大的$j$使得${d\choose j}$不是$p$的倍数(其中$1\le j<d$),将原式变形,即
$$
C(x)[x^{i+t}]=\frac{A(x)[x^{i+d-1}]-\sum_{j=0}^{t-1}{d\choose j}C(x)[x^{i+j}]-\sum_{j=t+1}^{d-1}{d\choose j}C(x)[x^{i+j}]}{{d\choose t}}
$$
注意到每向后迭代一次(最后一项),都会让$p$的幂次增加1

换言之,我们只需要将其分层迭代,每一层按次数从大到小迭代,并且当迭代到$i$之前后就不需要再迭代(直接取该值即可),那么每一层要迭代$o(d\alpha)$个数,每一个数迭代复杂度为$o(d)$,最多$\alpha$层,复杂度即$o(d^{2}\alpha^{2})$

同样预处理出这个线性的式子,再$o(md\alpha)$计算即可

时间复杂度为$O(d^{2}\log^{2}M+md\log M)$,可以通过

(事实上,前面Subtask4和Subtask5即$t=d-1$和$t=0$的情况)

  1 #include<bits/stdc++.h>
2 using namespace std;
3 #define N 3000005
4 #define D 105
5 #define L 35
6 vector<pair<int,int> >v;
7 int n,m,d,M,p,s,mod,Ans,mi[L],C[D][D],A[N+D*L],tot[D*L],Tot[D*L],f[N],ans[N];
8 int exgcd(int a,int b,int &x,int &y){
9 if (!b){
10 x=1,y=0;
11 return a;
12 }
13 int g=exgcd(b,a%b,y,x);
14 y-=a/b*x;
15 return g;
16 }
17 int get_inv(int k){
18 int x,y;
19 exgcd(k,mod,x,y);
20 return (x%mod+mod)%mod;
21 }
22 struct num{
23 int r,k;
24 num(){
25 r=1,k=0;
26 }
27 num(int rr){
28 r=rr,k=0;
29 if (!r)return;
30 while (r%p==0){
31 r/=p;
32 k++;
33 }
34 }
35 num(int rr,int kk){
36 r=rr,k=kk;
37 }
38 num operator * (const num &a)const{
39 return num(1LL*r*a.r%mod,k+a.k);
40 }
41 num inv(){
42 return num(get_inv(r),-k);
43 }
44 int get(){
45 if (k>=s)return 0;
46 return 1LL*r*mi[k]%mod;
47 }
48 };
49 void calc(){
50 mi[0]=1;
51 for(int i=1;i<s;i++)mi[i]=mi[i-1]*p;
52 for(int i=0;i<=d;i++){
53 C[i][0]=C[i][i]=1;
54 for(int j=1;j<d;j++)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
55 }
56 num ans=num(1);
57 for(int i=0;i<=m+s*d;i++){
58 if (n*d<i)ans=num(0);
59 else ans=ans*num(n*d-i)*num(i+1).inv();
60 A[i]=ans.get();
61 }
62 int t=0;
63 for(int i=1;i<d;i++)
64 if (C[d][i]%p)t=i;
65 int inv=get_inv(C[d][t]);
66 memset(tot,0,sizeof(tot));
67 memset(Tot,0,sizeof(Tot));
68 tot[d]=1;
69 for(int i=0;i<s;i++)
70 for(int j=d*s;j>=d;j--){
71 Tot[j]=(Tot[j]+1LL*inv*tot[j])%mod;
72 for(int k=0;k<d;k++)
73 if (k!=t)tot[j+k-t]=(tot[j+k-t]-1LL*C[d][k]*inv%mod*tot[j]%mod+mod)%mod;
74 tot[j]=0;
75 }
76 for(int i=0;i<m;i++){
77 f[i]=0;
78 for(int j=1;j<=min(i,d-1);j++)f[i]=(f[i]+1LL*tot[d-j]*f[i-j]%mod)%mod;
79 for(int j=d;j<=d*s;j++)f[i]=(f[i]+1LL*Tot[j]*A[i+j-t-1])%mod;
80 }
81 }
82 int main(){
83 scanf("%d%d%d%d",&n,&m,&d,&M);
84 int k=M;
85 for(int i=2;i*i<=k;i++){
86 int s=0;
87 while (k%i==0){
88 k/=i;
89 s++;
90 }
91 if (s)v.push_back(make_pair(i,s));
92 }
93 if (k>1)v.push_back(make_pair(k,1));
94 k=1;
95 for(int i=0;i<v.size();i++){
96 p=v[i].first,s=v[i].second,mod=1;
97 for(int j=0;j<s;j++)mod*=p;
98 calc();
99 int x=get_inv(k),kk=k*mod;
100 for(int j=0;j<m;j++)ans[j]=(1LL*x*(f[j]-ans[j]+kk)%kk*k+ans[j])%kk;
101 k=kk;
102 }
103 for(int i=0;i<m;i++)Ans^=ans[i];
104 printf("%d",Ans);
105 }

[loj3075]组合数求和的更多相关文章

  1. HDU 4704 Sum(隔板原理+组合数求和公式+费马小定理+快速幂)

    题目传送:http://acm.hdu.edu.cn/showproblem.php?pid=4704 Problem Description   Sample Input 2 Sample Outp ...

  2. ACM-ICPC 2018 焦作赛区网络预赛G Give Candies(隔板定理 + 小费马定理 + 大数取模,组合数求和)题解

    题意:给你n个东西,叫你把n分成任意段,这样的分法有几种(例如3:1 1 1,1 2,2 1,3 :所以3共有4种),n最多有1e5位,答案取模p = 1e9+7 思路:就是往n个东西中间插任意个板子 ...

  3. [hdu5226]组合数求和取模(Lucas定理)

    题意:给一个矩阵a,a[i][j] = C[i][j](i>=j) or 0(i < j),求(x1,y1),(x2,y2)这个子矩阵里面的所有数的和. 思路:首先问题可以转化为求(0,0 ...

  4. HDU 6333.Problem B. Harvest of Apples-组合数C(n,0)到C(n,m)求和-组合数学(逆元)+莫队 ((2018 Multi-University Training Contest 4 1002))

    2018 Multi-University Training Contest 4 6333.Problem B. Harvest of Apples 题意很好懂,就是组合数求和. 官方题解: 我来叨叨 ...

  5. HDU 4869 Turn the pokers (2014多校联合训练第一场1009) 解题报告(维护区间 + 组合数)

    Turn the pokers Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) ...

  6. Chosen by god【组合数打表】

    Chosen by god 题目链接(点击) Everyone knows there is a computer game names "hearth stone", recen ...

  7. HDU 5833 Zhu and 772002

    HDU 5833 Zhu and 772002 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/ ...

  8. [刷题]Codeforces 785D - Anton and School - 2

    Description As you probably know, Anton goes to school. One of the school subjects that Anton studie ...

  9. 朱世杰恒等式的应用-以CF841C为例

    题目大意 Codeforces 841C Leha and Function. 令\(F(n,k)\)为在集合\(\{x|x \in [1,n]\}\)中选择一个大小为k的子集,最小元素的期望值. 给 ...

随机推荐

  1. C语言日记② 初识 C的内存

    第一节: 上一个笔记 有趣的恶搞小程序 定时关机 #define _CRT_SECURE_NO_WARNINGS 1 #include <stdio.h> #include <str ...

  2. RobotFramework+Selenium如何提高脚本稳定性

     通过RF来跑selenium的脚本,正常运行一遍都没有问题,但如果要多次运行,提高脚本的稳定性,那么应该如何做呢?  当然有时候最简单最简单的方法就是直接通过sleep来等待,虽然简单粗暴,但会带来 ...

  3. CF193D Two Segments (线段树+dp)(外加两个扩展题)

    大概算是个系列整理 (最强版是模拟赛原题)) 首先,我们先来看这个题目. QWQ一开始是毫无头绪,除了枚举就是枚举 首先,我们可以枚举一个右端点,然后算一下当前右端点的答案 我们令\(f[l,r]\) ...

  4. 无网环境安装docker之--rpm

    总体思路:找一台可以联网的linux,下载docker的RPM依赖包而不进行安装(yum localinstall),将所有依赖的rpm环境打包好,再在无网环境中解压逐一安装(rpm:  --forc ...

  5. k8s replicaset controller分析(2)-核心处理逻辑分析

    replicaset controller分析 replicaset controller简介 replicaset controller是kube-controller-manager组件中众多控制 ...

  6. 离线状态迁移Anaconda虚拟环境

    离线状态迁移Anaconda虚拟环境 同样是项目需求,需要布署的服务器上的Anaconda安装到了普通账户下 而后续所有的内容都需要通过root账户进行操作,而服务器已经布署,联网比较麻烦 本文提出, ...

  7. JVM:Java中的引用

    JVM:Java中的引用 本笔记是根据bilibili上 尚硅谷 的课程 Java大厂面试题第二季 而做的笔记 在原来的时候,我们谈到一个类的实例化 Person p = new Person() 在 ...

  8. JVM:内存模型

    JVM:内存模型 说明:这是看了 bilibili 上 黑马程序员 的课程 JVM完整教程 后做的笔记 1. java 内存模型 很多人将[java 内存结构]与[java 内存模型]傻傻分不清,[j ...

  9. 配置 JAVA 环境 JDK + IDEA

    配置JDK 搜索 ORACLE 官网,找到 JDK,下载 JDK8 版本 / JDK11 版本 选择合适的路径,我这里放在了 D 盘 配置下方系统环境变量,变量名为 JAVA_HOME,把刚刚安装的J ...

  10. 热身训练3 Palindrome

    Palindrome 简要题意:  我们有一个字符串S,字符串的长度不超过500000. 求满足S[i]=S[2n−i]=S[2n+i−2](1≤i≤n)(n≥2)的子串个数.  分析: 我们能通过简 ...