题意:给定方程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函数处先预处理阶乘。

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

 #include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+;
ll n,m,n1,n2,MOD,a[N];
ll tot=,f[N],c[N]; ll fac[N];
void Initfac(ll p,ll pr) { //预处理阶乘
fac[]=;
for(ll i=;i<=pr;i++)
if(i%p) fac[i]=fac[i-]*i%pr;
else fac[i]=fac[i-];
} ll Pow(ll a,ll b,ll P){
ll ans=;
for(;b;b>>=,a=a*a%P)
if(b&) ans=ans*a%P;
return ans;
}
void exgcd(ll a,ll b,ll &d,ll &x,ll &y){
if(b==) d=a,x=,y=;
else exgcd(b,a%b,d,y,x),y-=(a/b)*x;
}
ll Inv(ll a,ll n){
ll d,x,y;
exgcd(a,n,d,x,y);
return d==?(x+n)%n:-;
}
ll Fac(ll n,ll p,ll pr){
if(n==) return ;
ll re=;
//for(ll i=2;i<=pr;i++) if(i%p) re=re*i%pr;
re=fac[pr];
re=Pow(re,n/pr,pr);
ll r=n%pr;
//for(int i=2;i<=r;i++) if(i%p) re=re*i%pr;
re=re*fac[r]%pr;
return re*Fac(n/p,p,pr)%pr;
}
ll C(ll n,ll m,ll p,ll pr){
if(n<m) return ;
Initfac(p,pr); //预处理阶乘
ll x=Fac(n,p,pr),y=Fac(m,p,pr),z=Fac(n-m,p,pr);
ll c=;
for(ll i=n;i;i/=p) c+=i/p;
for(ll i=m;i;i/=p) c-=i/p;
for(ll i=n-m;i;i/=p) c-=i/p;
ll a=x*Inv(y,pr)%pr*Inv(z,pr)%pr*Pow(p,c,pr)%pr;
return a*(MOD/pr)%MOD*Inv(MOD/pr,pr)%MOD;
}
ll Lucas(ll n,ll m){ //exLucas
ll x=MOD,re=;
// for(ll i=2;i<=MOD;i++) if(x%i==0){
// ll pr=1;
// while(x%i==0) x/=i,pr*=i;
// re=(re+C(n,m,i,pr))%MOD;
// }
for (int i=;i<=tot;i++) re=(re+C(n,m,f[i],c[i]))%MOD;
return re;
} void prework(ll n) {
ll t=n;
for (int i=;(ll)i*i<=n;i++) {
if (t%i==) {
tot++; f[tot]=i; c[tot]=;
while (t%i==) t/=i,c[tot]*=i;
}
}
if (t>) f[++tot]=t,c[tot]=t;
} int main()
{
int T; scanf("%d%lld",&T,&MOD);
prework(MOD);
while(T--) {
scanf("%lld%d%d%lld",&n,&n1,&n2,&m);
for(int i=;i<=n1+n2;i++) scanf("%lld",&a[i]);
for(int i=;i<=n2;i++) m-=a[n1+i]-;
m-=n; ll ans=;
for(int i=;i<(<<n1);i++) {
int tot=;
ll x=m;
for(int j=;j<n1;j++)
if (i&(<<j)) { tot++; x-=a[j+]; }
if (tot%) ans=(ans-Lucas(x+n-,n-)+MOD)%MOD;
else ans=(ans+Lucas(x+n-,n-))%MOD;
}
printf("%lld\n",ans);
}
return ;
}

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

 ll Pow(ll a,ll b,ll P){
ll ans=;
for(;b;b>>=,a=a*a%P)
if(b&) ans=ans*a%P;
return ans;
}
void exgcd(ll a,ll b,ll &d,ll &x,ll &y){
if(b==) d=a,x=,y=;
else exgcd(b,a%b,d,y,x),y-=(a/b)*x;
}
ll Inv(ll a,ll n){
ll d,x,y;
exgcd(a,n,d,x,y);
return d==?(x+n)%n:-;
}
ll Fac(ll n,ll p,ll pr){
if(n==) return ;
ll re=;
for(ll i=;i<=pr;i++) if(i%p) re=re*i%pr;
re=Pow(re,n/pr,pr);
ll r=n%pr;
for(int i=;i<=r;i++) if(i%p) re=re*i%pr;
return re*Fac(n/p,p,pr)%pr;
}
ll C(ll n,ll m,ll p,ll pr){
if(n<m) return ;
ll x=Fac(n,p,pr),y=Fac(m,p,pr),z=Fac(n-m,p,pr);
ll c=;
for(ll i=n;i;i/=p) c+=i/p;
for(ll i=m;i;i/=p) c-=i/p;
for(ll i=n-m;i;i/=p) c-=i/p;
ll a=x*Inv(y,pr)%pr*Inv(z,pr)%pr*Pow(p,c,pr)%pr;
return a*(MOD/pr)%MOD*Inv(MOD/pr,pr)%MOD;
}
ll Lucas(ll n,ll m){
ll x=MOD,re=;
for(ll i=;i<=MOD;i++) if(x%i==){
ll pr=;
while(x%i==) x/=i,pr*=i;
re=(re+C(n,m,i,pr))%MOD;
}
return re;
}

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. Spring Cloud Commons教程(二)Spring RestTemplate作为负载平衡器客户端

    RestTemplate可以自动配置为使用功能区.要创建负载平衡RestTemplate创建RestTemplate @Bean并使用@LoadBalanced限定符. 警告 通过自动配置不再创建Re ...

  2. CG-CTF | Hello,RE!

    菜狗开始向着pwn与re进军了(●'◡'●)[说白了,还是在水博客吧] 按r出flag: galf    leW{    emoc    _oT_    W_ER  dlro   }! 反一下:fla ...

  3. [CSP-S模拟测试]:题(DP+数学)

    题目描述 出个题就好了.这就是出题人没有写题目背景的原因.你在平面直角坐标系上.你一开始位于$(0,0)$.每次可以在上/下/左/右四个方向中选一个走一步.即:从$(x,y)$走到$(x,y+1),( ...

  4. 【l转】VS2015下解决:无法解析的外部符号 __imp___vsnprintf 及__iob_func

    https://blog.csdn.net/hebbely/article/details/53780562

  5. 阶段1 语言基础+高级_1-3-Java语言高级_06-File类与IO流_04 IO字节流_3_字节输出流_OutputStream类&FileOutputStream

    都在IO包下 所有字节输出最顶层的父类 它是一个抽象类.abstract修饰的 一般这种类定义的都是所有字节流都可以使用公共的方法,

  6. Swiper轮播隐藏再显示后不动

    公告用Swiper轮播方式,在某些不需要显示公告的页面进行隐藏,在需要展示公告的页面进行显示时候,公告不能正常轮播,在条件里加入重新设置轮播方法等网上的一些方法仍然不行,最后解决方法: this.my ...

  7. js面向对象程序设计之继承

    在面向对象语言中继承分成两种:接口继承和实现继承.解释一下,接口继承只继承方法的签名,而实现继承则是继承实际的方法.但是ECMAScript中的函数没有签名所以无法进行接口继承,只能是实现实现继承.而 ...

  8. Symmetric Tree(对称二叉树)

    来源:https://leetcode.com/problems/symmetric-tree Given a binary tree, check whether it is a mirror of ...

  9. [c#]Extesion method

    做一个类似Vb.net里面with的方法 public static void Use<T>(this T item, Action<T> work) { work(item) ...

  10. js转换后台接受的日期格式

    var html = "--";if(data.createTime!=null&&data.createTime!=""){ Date.pro ...