题意:给定方程x1+x2+....xn=m,每个x是正整数。但是对前n1个数做了限制x1<=a1,x2<=a2...xn1<=an1,同时对第n1+1到n1+n2个数也做了限制xn1+1>=an1+1....xn1+n2>=an1+n2,输出方程解个数。

解法:首先如果对数字没有任何要求(应该是只要求是非负数)的话,答案就是C(n+m+1,m+1)原理是隔板法。但是此题有各种限制,我们想办法解决限制使得答案往无限制上面靠。

首先是解决要正整数,那么每个数字减一即可,就是m-=n。

然后对于n1+1到n1+n2的限制,大于等于的限制也简单,也是xi>=ai的话就使xi-=ai即可。

好了到最麻烦的xi<=ai限制,这个限制我们没办法通过数字处理来解决。但是我们观察到这些限制个数小于等于8个,自然会想到容斥原理。

那么容斥原理常规套路,无限制-至少一个突破限制(也就是xi>ai为突破限制)方案数+至少两个数字突破限制.........

ok,解题思路就是上面这些。但是这题比较麻烦的在于:要计算的组合数非常大且模数不为质数!!!那么Lucas定理也不管用了,我们只能用到exLucas定理。

推荐看这篇博客:https://www.cnblogs.com/candy99/p/6637629.html

直接套上大佬的exLucas会TLE,有一些地方需要优化,①Lucas函数内每次都要找MOD的因子太慢了,先预处理出来。②Fac函数内每次暴力计算阶乘太慢了,需要在调用Fac之前即C函数处先预处理阶乘。

此题代码(注释的是修改大佬模板地方,加上优化):

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. typedef long long ll;
  4. const int N=1e5+;
  5. ll n,m,n1,n2,MOD,a[N];
  6. ll tot=,f[N],c[N];
  7.  
  8. ll fac[N];
  9. void Initfac(ll p,ll pr) { //预处理阶乘
  10. fac[]=;
  11. for(ll i=;i<=pr;i++)
  12. if(i%p) fac[i]=fac[i-]*i%pr;
  13. else fac[i]=fac[i-];
  14. }
  15.  
  16. ll Pow(ll a,ll b,ll P){
  17. ll ans=;
  18. for(;b;b>>=,a=a*a%P)
  19. if(b&) ans=ans*a%P;
  20. return ans;
  21. }
  22. void exgcd(ll a,ll b,ll &d,ll &x,ll &y){
  23. if(b==) d=a,x=,y=;
  24. else exgcd(b,a%b,d,y,x),y-=(a/b)*x;
  25. }
  26. ll Inv(ll a,ll n){
  27. ll d,x,y;
  28. exgcd(a,n,d,x,y);
  29. return d==?(x+n)%n:-;
  30. }
  31. ll Fac(ll n,ll p,ll pr){
  32. if(n==) return ;
  33. ll re=;
  34. //for(ll i=2;i<=pr;i++) if(i%p) re=re*i%pr;
  35. re=fac[pr];
  36. re=Pow(re,n/pr,pr);
  37. ll r=n%pr;
  38. //for(int i=2;i<=r;i++) if(i%p) re=re*i%pr;
  39. re=re*fac[r]%pr;
  40. return re*Fac(n/p,p,pr)%pr;
  41. }
  42. ll C(ll n,ll m,ll p,ll pr){
  43. if(n<m) return ;
  44. Initfac(p,pr); //预处理阶乘
  45. ll x=Fac(n,p,pr),y=Fac(m,p,pr),z=Fac(n-m,p,pr);
  46. ll c=;
  47. for(ll i=n;i;i/=p) c+=i/p;
  48. for(ll i=m;i;i/=p) c-=i/p;
  49. for(ll i=n-m;i;i/=p) c-=i/p;
  50. ll a=x*Inv(y,pr)%pr*Inv(z,pr)%pr*Pow(p,c,pr)%pr;
  51. return a*(MOD/pr)%MOD*Inv(MOD/pr,pr)%MOD;
  52. }
  53. ll Lucas(ll n,ll m){ //exLucas
  54. ll x=MOD,re=;
  55. // for(ll i=2;i<=MOD;i++) if(x%i==0){
  56. // ll pr=1;
  57. // while(x%i==0) x/=i,pr*=i;
  58. // re=(re+C(n,m,i,pr))%MOD;
  59. // }
  60. for (int i=;i<=tot;i++) re=(re+C(n,m,f[i],c[i]))%MOD;
  61. return re;
  62. }
  63.  
  64. void prework(ll n) {
  65. ll t=n;
  66. for (int i=;(ll)i*i<=n;i++) {
  67. if (t%i==) {
  68. tot++; f[tot]=i; c[tot]=;
  69. while (t%i==) t/=i,c[tot]*=i;
  70. }
  71. }
  72. if (t>) f[++tot]=t,c[tot]=t;
  73. }
  74.  
  75. int main()
  76. {
  77. int T; scanf("%d%lld",&T,&MOD);
  78. prework(MOD);
  79. while(T--) {
  80. scanf("%lld%d%d%lld",&n,&n1,&n2,&m);
  81. for(int i=;i<=n1+n2;i++) scanf("%lld",&a[i]);
  82. for(int i=;i<=n2;i++) m-=a[n1+i]-;
  83. m-=n;
  84.  
  85. ll ans=;
  86. for(int i=;i<(<<n1);i++) {
  87. int tot=;
  88. ll x=m;
  89. for(int j=;j<n1;j++)
  90. if (i&(<<j)) { tot++; x-=a[j+]; }
  91. if (tot%) ans=(ans-Lucas(x+n-,n-)+MOD)%MOD;
  92. else ans=(ans+Lucas(x+n-,n-))%MOD;
  93. }
  94. printf("%lld\n",ans);
  95. }
  96. return ;
  97. }

记录下大佬的exLucas定理模板:

  1. ll Pow(ll a,ll b,ll P){
  2. ll ans=;
  3. for(;b;b>>=,a=a*a%P)
  4. if(b&) ans=ans*a%P;
  5. return ans;
  6. }
  7. void exgcd(ll a,ll b,ll &d,ll &x,ll &y){
  8. if(b==) d=a,x=,y=;
  9. else exgcd(b,a%b,d,y,x),y-=(a/b)*x;
  10. }
  11. ll Inv(ll a,ll n){
  12. ll d,x,y;
  13. exgcd(a,n,d,x,y);
  14. return d==?(x+n)%n:-;
  15. }
  16. ll Fac(ll n,ll p,ll pr){
  17. if(n==) return ;
  18. ll re=;
  19. for(ll i=;i<=pr;i++) if(i%p) re=re*i%pr;
  20. re=Pow(re,n/pr,pr);
  21. ll r=n%pr;
  22. for(int i=;i<=r;i++) if(i%p) re=re*i%pr;
  23. return re*Fac(n/p,p,pr)%pr;
  24. }
  25. ll C(ll n,ll m,ll p,ll pr){
  26. if(n<m) return ;
  27. ll x=Fac(n,p,pr),y=Fac(m,p,pr),z=Fac(n-m,p,pr);
  28. ll c=;
  29. for(ll i=n;i;i/=p) c+=i/p;
  30. for(ll i=m;i;i/=p) c-=i/p;
  31. for(ll i=n-m;i;i/=p) c-=i/p;
  32. ll a=x*Inv(y,pr)%pr*Inv(z,pr)%pr*Pow(p,c,pr)%pr;
  33. return a*(MOD/pr)%MOD*Inv(MOD/pr,pr)%MOD;
  34. }
  35. ll Lucas(ll n,ll m){
  36. ll x=MOD,re=;
  37. for(ll i=;i<=MOD;i++) if(x%i==){
  38. ll pr=;
  39. while(x%i==) x/=i,pr*=i;
  40. re=(re+C(n,m,i,pr))%MOD;
  41. }
  42. return re;
  43. }

BZOJ3129/洛谷P3301方程(SDOI2013)容斥原理+扩展Lucas定理的更多相关文章

  1. BZOJ3129 SDOI2013方程(容斥原理+扩展lucas)

    没有限制的话算一个组合数就好了.对于不小于某个数的限制可以直接减掉,而不大于某个数的限制很容易想到容斥,枚举哪些超过限制即可. 一般情况下n.m.p都是1e9级别的组合数没办法算.不过可以发现模数已经 ...

  2. 题解-洛谷P5410 【模板】扩展 KMP(Z 函数)

    题面 洛谷P5410 [模板]扩展 KMP(Z 函数) 给定两个字符串 \(a,b\),要求出两个数组:\(b\) 的 \(z\) 函数数组 \(z\).\(b\) 与 \(a\) 的每一个后缀的 L ...

  3. 【learning】 扩展lucas定理

    首先说下啥是lucas定理: $\binom n m \equiv \binom {n\%P} {m\%P} \times \binom{n/P}{m/P} \pmod P$ 借助这个定理,求$\bi ...

  4. 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 ...

  5. BZOJ - 2142 礼物 (扩展Lucas定理)

    扩展Lucas定理模板题(貌似这玩意也只能出模板题了吧~~本菜鸡见识鄙薄,有待指正) 原理: https://blog.csdn.net/hqddm1253679098/article/details ...

  6. [bzoj2142]礼物(扩展lucas定理+中国剩余定理)

    题意:n件礼物,送给m个人,每人的礼物数确定,求方案数. 解题关键:由于模数不是质数,所以由唯一分解定理, $\bmod  = p_1^{{k_1}}p_2^{{k_2}}......p_s^{{k_ ...

  7. Lucas定理和扩展Lucas定理

    1.Lucas定理 首先给出式子:\(C_n^m\%p = C_{\lfloor\frac{n}{p}\rfloor}^{\lfloor\frac{m}{p}\rfloor} * C_{n\%p}^{ ...

  8. Ceizenpok’s formula Gym - 100633J 扩展Lucas定理 + 中国剩余定理

    http://codeforces.com/gym/100633/problem/J 其实这个解法不难学的,不需要太多的数学.但是证明的话,我可能给不了严格的证明.可以看看这篇文章 http://ww ...

  9. [笔记] 扩展Lucas定理

    [笔记] 扩展\(Lucas\)定理 \(Lucas\)定理:\(\binom{n}{m} \equiv \binom{n/P}{m/P} \binom{n \% P}{m \% P}\pmod{P} ...

随机推荐

  1. 安装JDK ,提示 错误1316 指定的账户已存在

    基于情况: 安装了一个JDK 后,在文件目录中删除了相关文件,之后再次安装,提示  错误1316 指定的账户已存在 造成原因:安装JDK,相当于安装了一个软件,要使用系统的软件卸载功能卸载,不能只删除 ...

  2. [CSP-S模拟测试]:环(图论+期望)

    题目传送门(内部题79) 输入格式 第一行读入两个整数$n,e$表示节点数及$cwystc$已确定的有向边边数. 接下来$e$行,每行两个整数$x,y$描述$cwystc$确定的边. 输出格式 输出一 ...

  3. VS 2010内存泄漏检测

    控制台程序在启动时调用 _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); 程序正常退出后会打印内存泄漏信息. MFC程序不用 ...

  4. 阿里云服务器+ubantu+nodejs 服务器基本配置流程

    所有步骤在MAC 电脑环境下操作 一.配置环境 1.连接到远程服务器 1.购买阿里云ECS服务器,我选用的 ubantu 14.0.4 (64位),购买的时候输入的密码记录下来,没有设置的话可以随后在 ...

  5. 虚拟主机支持apk

    扩展名中填写.apk MIME类型中填写apk的MIME类型  application/vnd.android.package-archive

  6. selenium启动firefox打开导入向导问题解决

    操作系统:win8-64位 火狐版本:40.0.2 问题描述:selenium启动firefox时,每次启动都提示我导入其他浏览器的页签,如下图所示 解决方法一: 到firefox的profiles. ...

  7. redis和memcached的对比与选型

    相似处:     1:Memcached与Redis都属于内存内.键值数据存储方案.均属于NoSQL家族,而且都基于同样的键值数据模型.双方都选择将全部数据保存在内存当中,这自然也就让它们成为非常理想 ...

  8. shell脚本一一项目6

    主题:获取网卡的流量 ifconfig 查看流量 文件流量数据量 脚本内容 #!/bin/bash#name: mark# check network dev's liuliangnic=$1 ech ...

  9. js 实现两个小数的相乘、相除功能

    <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...

  10. Tensorflow创建和读取17flowers数据集

    http://blog.csdn.net/sinat_16823063/article/details/53946549 Tensorflow创建和读取17flowers数据集 标签: tensorf ...