BZOJ3129: [Sdoi2013]方程
2017-06-01 18:41
351 查看
BZOJ3129
挺好的一道题呀。
其实p只会有三个值10007,262203414,437367875
将三个值分解质因数最大的也只有1012。数组可以开的下,不然就不可做了。
首先考虑没有限制。每一个任取,那就是隔板法 ans=Cn−1m−1
对于xi>=ai的限制,可以看做,第i个预先放好ai−1个,将m减去ai−1然后隔板法。(高中排列组合QAQ)
然后在考虑xi<=ai的限制。。好像没办法用一些排列组合的知识直接解决。
然后看到n1,n2<=8。好像可以容斥!那么就考虑xi>ai的情况然后容斥一下。
统计答案就是−奇数个,+偶数个。
后面容斥的时候是减ai不是ai−1。。QAQ卒于该点,傻不拉几的想都没想就直接打−1。
大组合数取模类似BZOJ2142
然后最后每次CRT合并一下,就结了。
。。偷懒没预处理阶乘和阶乘逆元跑了23s+。改一下就248ms了。
挺好的一道题呀。
其实p只会有三个值10007,262203414,437367875
将三个值分解质因数最大的也只有1012。数组可以开的下,不然就不可做了。
首先考虑没有限制。每一个任取,那就是隔板法 ans=Cn−1m−1
对于xi>=ai的限制,可以看做,第i个预先放好ai−1个,将m减去ai−1然后隔板法。(高中排列组合QAQ)
然后在考虑xi<=ai的限制。。好像没办法用一些排列组合的知识直接解决。
然后看到n1,n2<=8。好像可以容斥!那么就考虑xi>ai的情况然后容斥一下。
统计答案就是−奇数个,+偶数个。
后面容斥的时候是减ai不是ai−1。。QAQ卒于该点,傻不拉几的想都没想就直接打−1。
大组合数取模类似BZOJ2142
然后最后每次CRT合并一下,就结了。
。。偷懒没预处理阶乘和阶乘逆元跑了23s+。改一下就248ms了。
【代码】
#include <cstdio> #include <iostream> #include <algorithm> #define N 10205 #define INF 0x7fffffff using namespace std; typedef long long ll; ll read() { ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();} return x*f; } int T,Mod,n,m,n1,n2,cnt; int a[20]; ll p[10],pc[10],Fac[2][10] ,ans,tot,tmp; void Exgcd(ll a,ll b,ll &x,ll &y){ if(b) { Exgcd(b,a%b,y,x); y-=(a/b)*x; } else x=1,y=0; } ll Inv(ll a,ll b) { ll x,y; Exgcd(a,b,x,y); return (x%b+b)%b; } void Divide(int x) { for(int i=2;i*i<=x;i++) if(x%i==0) { p[++cnt]=i,pc[cnt]=1; while(x%i==0) x/=i,pc[cnt]*=i; } if(x!=1) p[++cnt]=pc[cnt]=x; for(int j=1;j<=cnt;j++) { Fac[1][j][0]=Fac[0][j][0]=1; for(int i=1;i<pc[j];i++) Fac[1][j][i]=Fac[1][j][i-1]*(i%p[j]?i:1)%pc[j]; for(int i=1;i<pc[j];i++) Fac[0][j][i]=Fac[0][j][i-1]*(i%p[j]?Inv(i,pc[j]):1)%pc[j]; } } ll Qpow(ll x,ll y,ll mod) { ll rtn=1; while(y) { if(y&1) rtn=rtn*x%mod; x=x*x%mod;y>>=1; } return rtn; } ll Calc(int now,int P,int Pc,int i,int j) { if(now<P) return Fac[j][i][now]; tot+=now/P; return Fac[j][i][now%Pc]*Qpow(Fac[j][i][Pc-1],now/Pc,Pc)%Pc*Calc(now/P,P,Pc,i,j)%Pc; } ll Get_Ans(int now,int nn,int P,int Pc,int i) { tot=0; ll t1=Calc(now,P,Pc,i,1); tmp=tot;tot=0; ll t2=Calc(nn,P,Pc,i,0)*Calc(now-nn,P,Pc,i,0)%Pc; return t1*t2%Pc*Qpow(P,tmp-tot,Pc)%Pc; } ll Solve(int now,int nn) { if(now<nn) return 0; ll rtn=0; for(int i=1;i<=cnt;i++) { ll r=Get_Ans(now,nn,p[i],pc[i],i),Mi=Mod/pc[i],t2=Inv(Mi,pc[i]); rtn=(rtn+r*Mi%Mod*t2%Mod)%Mod; } return rtn; } void Input_Init() { n=read(),n1=read(),n2=read(),m=read();ans=0; for(int i=1;i<=n1+n2;i++) { a[i]=read(); if(i>n1) m-=a[i]-1; } } void Work() { for(int i=0;i<(1<<n1);i++) { int sum=0,f=1,now=m; for(int j=0;j<n1;j++) if(i&(1<<j)) sum++,now-=a[j+1]; if(sum&1) f=-1; ans=(ans+f*(Solve(now-1,n-1))+Mod)%Mod; } printf("%lld\n\n",ans); } int main() { T=read(),Mod=read(); Divide(Mod); while(T--) { Input_Init(); Work(); } return 0; }
相关文章推荐
- bzoj千题计划267:bzoj3129: [Sdoi2013]方程
- bzoj3129 [Sdoi2013]方程 容斥+扩展lucas
- 【SDOI2013】【BZOJ 3129】【JZOJ 3214】方程
- BZOJ 3129 SDOI2013 方程
- BZOJ 3129 [Sdoi2013]方程 不定方程解的个数+组合数取模
- bzoj 3129: [Sdoi2013]方程(容斥原理+组合数学+数论)
- [BZOJ3129][Sdoi2013]方程(容斥原理+扩展lucas)
- [BZOJ3129][SDOI2013]方程(扩展Lucas定理+容斥)
- BZOJ_3129_[Sdoi2013]方程_组合数学+容斥原理
- BZOJ3129: [Sdoi2013]方程
- bzoj 3129: [Sdoi2013]方程
- BZOJ 3129 方程[SDOI2013]
- [BZOJ 3129] [Sdoi2013] 方程 【容斥+组合数取模+中国剩余定理】
- bzoj 3129 [Sdoi2013]方程 数论 容斥
- bzoj3129[Sdoi2013]方程 exlucas+容斥原理
- ●BZOJ 3129 [Sdoi2013]方程
- 【SDOI2013】【BZOJ 3129】方程 (转)
- bzoj千题计划258:bzoj3123: [Sdoi2013]森林
- BZOJ 3123: [Sdoi2013]森林
- bzoj 3130 [Sdoi2013]费用流(二分,最大流)