题目链接:BZOJ - 3129

题目分析

使用隔板法的思想,如果没有任何限制条件,那么方案数就是 C(m - 1, n - 1)。

如果有一个限制条件是 xi >= Ai ,那么我们就可以将 m 减去 Ai - 1 ,相当于将这一部分固定分给 xi,就转化为无限制的情况了。

如果有一些限制条件是 xi <= Ai 呢?直接来求就不行了,但是注意到这样的限制不超过 8 个,我们可以使用容斥原理来求。

考虑容斥:考虑哪些限制条件被违反了,也就是说,有哪些限制为 xi <= Ai 却是 xi > Ai,这样就转化为了 xi >= Ai 的限制条件。

那么我们就可以在 2^8 * T(求组合数) 的时间内求出答案了。

怎么求这个组合数呢?直接预处理阶乘的逆元是不可以的,因为模数不都是质数。

我们要将模数拆成一个个 pi^ai 这样的形式,使得它们两两之间互质,就可以分别求出答案,最后再用中国剩余定理组合起来。

中国剩余定理:如果有n个方程 x = xi (mod mi) ,M = m1 * m2 * .. * mn ,那么在 mod M 的意义下,方程组有一个唯一解。

x = sigma(Mi * Inv(Mi) * xi) % M ,其中 Mi = M / mi ,Inv(Mi)是Mi在mod mi意义下的逆元。

那么我们的问题就是,如何求出 C(n, m) % (p^a) 。

这里就需要用到“组合数取模”了,专门用来求解这种问题。

使用类似于快速阶乘的方法,将组合数中分数线上下的阶乘都拆成 e * p^f 的形式,然后 e 直接计算,f 分数线上下相减之后再计算。

怎么将 x! 拆成 e * p^f 呢?

假设我们要 mod 的数是 p^a ,那么我们需要预处理出 [1, p^a - 1] 中除去 p 的倍数的其余数的前缀积(类似阶乘少了 p 的倍数)。

然后我们知道 [1, x] 中包含 p 的数有 x / p 个,我们将这些数中都提取出 1 个 p,那么就获得了 p^(x/p),然后这 x / p 个数就变成了 [1, x/p],就可以递归下去。

其余的部分可以分段来求,分成 [1, p^a - 1], [p^a + 1, p^a + p^a - 1] ..... 这样,每一段的积都是一样的 (mod p^a 意义下),直接快速幂就可以了。

最后还会剩下一段 [1, x % (p^a)] ,也是直接预处理出的值。

这样这道题就做完了(呼~)。

另外注意的是,在写代码的时候,我求逆元使用欧拉定理但是确用错了。

欧拉定理:a^phi(b) = 1 (mod b) 条件:gcd(a, b) = 1

注意是 a^phi(b) 而不是 a^(b-1) !当 b 不是质数的时候就跪了!

代码

#include <iostream>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cstdio> using namespace std; typedef long long LL;
typedef double LF; const int MaxP = 10201 + 15, MaxN1 = 8 + 5; int T, p, n, n1, n2, m, Top, Ans;
int A[MaxN1]; LL Temp;
LL Fac[10][MaxP], Pr[10], Pi[10], Pa[10], Phi_Pi[10], Mi[10], Inv_Mi[10], Xi[10]; LL Pow(LL a, LL b, LL Mod)
{
LL ret, f;
ret = 1; f = a;
while (b)
{
if (b & 1)
{
ret *= f;
ret %= Mod;
}
b >>= 1;
f *= f;
f %= Mod;
}
return ret;
} void Prepare()
{
int x, SqrtX;
x = p; SqrtX = (int)sqrt((LF)x);
Top = 0;
for (int i = 2; i <= SqrtX; ++i)
{
if (x % i != 0) continue;
Pr[++Top] = i;
Pa[Top] = 0;
Pi[Top] = 1;
while (x % i == 0)
{
++Pa[Top];
Pi[Top] *= i;
x /= i;
}
Phi_Pi[Top] = Pi[Top] / Pr[Top] * (Pr[Top] - 1);
}
if (x > 1)
{
Pr[++Top] = x;
Pa[Top] = 1;
Pi[Top] = x;
Phi_Pi[Top] = Pi[Top] - 1;
}
for (int i = 1; i <= Top; ++i)
{
Mi[i] = p / Pi[i];
Inv_Mi[i] = Pow(Mi[i], Phi_Pi[i] - 1, Pi[i]);
Fac[i][0] = 1;
for (int j = 1; j < Pi[i]; ++j)
{
if (j % Pr[i] != 0) Fac[i][j] = Fac[i][j - 1] * j % Pi[i];
else Fac[i][j] = Fac[i][j - 1];
}
}
} struct ES
{
LL e, f;
}; ES Calc(int x, int k)
{
ES ret, tc;
if (x < Pr[k])
{
ret.e = Fac[k][x];
ret.f = 0;
return ret;
}
ret.f = x / Pr[k];
tc = Calc(x / Pr[k], k);
ret.f += tc.f;
ret.e = tc.e * Fac[k][x % Pi[k]] % Pi[k];
ret.e = ret.e * Pow(Fac[k][Pi[k] - 1], x / Pi[k], Pi[k]) % Pi[k];
return ret;
} LL C(int x, int y, int k)
{
LL ret;
int pf;
ES Ex, Ey, Exy;
Ex = Calc(x, k);
Ey = Calc(y, k);
Exy = Calc(x - y, k);
ret = Ex.e * Pow(Ey.e, Phi_Pi[k] - 1, Pi[k]) % Pi[k] * Pow(Exy.e, Phi_Pi[k] - 1, Pi[k]) % Pi[k];
pf = Ex.f - Ey.f - Exy.f;
if (pf >= Pa[k]) ret = 0;
else ret = ret * Pow(Pr[k], pf, Pi[k]) % Pi[k];
return ret;
} int C(int x, int y)
{
if (x == y) return 1;
if (x < y) return 0;
if (y == 0) return 1;
LL ret = 0;
for (int i = 1; i <= Top; ++i) Xi[i] = C(x, y, i);
for (int i = 1; i <= Top; ++i)
{
ret += Xi[i] * Mi[i] % p * Inv_Mi[i] % p;
ret %= p;
}
return (int)ret;
} void DFS(int x, int Cnt, int Sum)
{
if (x == n1)
{
if (Cnt & 1) Temp -= C(m - Sum - 1, n - 1);
else Temp += C(m - Sum - 1, n - 1);
Temp = (Temp % p + p) % p;
return;
}
DFS(x + 1, Cnt, Sum);
DFS(x + 1, Cnt + 1, Sum + A[x + 1]);
} int Solve()
{
Temp = 0;
DFS(1, 0, 0);
DFS(1, 1, A[1]);
return (int)Temp;
} int main()
{
scanf("%d%d", &T, &p);
Prepare();
for (int Case = 1; Case <= T; ++Case)
{
scanf("%d%d%d%d", &n, &n1, &n2, &m);
for (int i = 1; i <= n1; ++i) scanf("%d", &A[i]);
int Num;
for (int i = 1; i <= n2; ++i)
{
scanf("%d", &Num);
m -= Num - 1;
}
if (n1 > 0) Ans = Solve();
else Ans = C(m - 1, n - 1);
printf("%d\n", Ans);
}
return 0;
}

  

[BZOJ 3129] [Sdoi2013] 方程 【容斥+组合数取模+中国剩余定理】的更多相关文章

  1. ●BZOJ 3129 [Sdoi2013]方程

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3129 题解: 容斥,扩展Lucas,中国剩余定理 先看看不管限制,只需要每个位置都是正整数时 ...

  2. BZOJ 3129 [SDOI2013]方程 (拓展Lucas)

    题目大意:给定一个方程$X_{1}+X_{2}+X_{3}+X_{4}+...+X_{n}=M$,$\forall X_{i}<=A_{i} (i<=n1)$ $\forall X_{i} ...

  3. BZOJ 3129 SDOI2013 方程

    如果没有限制,答案直接用隔板法C(m-1,n-1) 对于>=x的限制,我们直接在对应位置先放上x-1即可,即m=m-(x-1) 对于<=x的限制,由于限制很小我们可以利用容斥原理将它转化为 ...

  4. bzoj 3202 [Sdoi2013]项链——容斥+置换+推式子

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3202 可见Zinn博客:https://www.cnblogs.com/Zinn/p/100 ...

  5. 组合数取模Lucas定理及快速幂取模

    组合数取模就是求的值,根据,和的取值范围不同,采取的方法也不一样. 下面,我们来看常见的两种取值情况(m.n在64位整数型范围内) (1)  , 此时较简单,在O(n2)可承受的情况下组合数的计算可以 ...

  6. 排列组合+组合数取模 HDU 5894

    // 排列组合+组合数取模 HDU 5894 // 题意:n个座位不同,m个人去坐(人是一样的),每个人之间至少相隔k个座位问方案数 // 思路: // 定好m个人 相邻人之间k个座位 剩下就剩n-( ...

  7. hdu 3944 DP? 组合数取模(Lucas定理+预处理+帕斯卡公式优化)

    DP? Problem Description Figure 1 shows the Yang Hui Triangle. We number the row from top to bottom 0 ...

  8. lucas定理解决大组合数取模

    LL MyPow(LL a, LL b) { LL ret = ; while (b) { ) ret = ret * a % MOD; a = a * a % MOD; b >>= ; ...

  9. 2015 ICL, Finals, Div. 1 Ceizenpok’s formula(组合数取模,扩展lucas定理)

    J. Ceizenpok’s formula time limit per test 2 seconds memory limit per test 256 megabytes input stand ...

随机推荐

  1. Linux性能及调优指南(翻译)

    http://blog.csdn.net/ljianhui/article/details/46718835 http://blog.chinaunix.net/uid-26000296-id-406 ...

  2. 使用Git操作GitHub代码入门教程

    GitHub除了网页操作外,还可以借助本地客户端git(或github for windows)来增删修改远程代码.使用Git操作来连接GitHub可以通过Https或SSH方式,使用SSH方式可以免 ...

  3. 第八篇:web之前端踩的一些坑

    前端踩的一些坑   前端踩的一些坑 本节内容 事件代理 清除标签的所有事件 bootstrap的模态框自定义方法 ajax在django里面实现post提交 ajax提交数据嵌套 1.事件代理 之前写 ...

  4. C#/.net七牛云存储上传图片(文件)操作

    七牛云存储官方: C#SDK(http://developer.qiniu.com/docs/v6/sdk/csharp-sdk.html) 注册成为标准用户就可获得:10GB永久免费存储空间/ 每月 ...

  5. Base64的Java代码实现

    欢迎拍砖~ 在数据二进制和byte互相转换的地方方法写得有点挫,不知道有没有更好的方法~ 顺便复习了java的一些基础东西,如位操作,原码反码补码 可以在这篇blog里学习到详细的知识点:http:/ ...

  6. MVC 中的Areas支持

    在ASP.NET MVC 2中对于Area功能的增强,这样的增强是如何在同一个项目中更好地组织应用程序的? ASP.NET MVC 1.0时,如果我们要在一个项目中做自己网站的后台应用,而又保持URL ...

  7. 不安装oracle客户端,连接到服务器的oracle (注:针对 odp.net)

    前几天在研究怎样不安装oracle客户端去访问oracle,并把里面的数据同步到本地的Sql Server数据库中. 准备工作:首先你得有如下.dll,我这个是针对oracle10g的,如果是更高的版 ...

  8. asp IIS部署An error occurred on the server when processing the URL错误提示解决

    An error occurred on the server when processing the URL. Please contact the system administrator.If ...

  9. 收集SQLServer线程等待信息

    要知道线程等待时间是制约SQL Server效率的重要原因,这一个随笔中将学习怎样收集SQL Server中的线程等待时间,类型等信息,这些信息是进行数据库优化的依据. sys.dm_os_wait_ ...

  10. Mybatis的学习总结:mybatis的入门介绍

    一.myBatis简述 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以 ...