您的位置:首页 > 其它

bzoj3129 [Sdoi2013]方程 容斥+扩展lucas

2018-01-24 19:20 363 查看
调了两天,全是低级错误和脑子问题

对于>=的,直接用m减掉

对于<=的,一开始想枚举减多少,但发现对于每个枚举的值是独立的,所以是1e9的

然后由于>=和<=是两个对立的情况,所以直接用容斥,合法的减掉不合法的

但由于我简单容斥做多了,所以就直接用全合法的-全不合法的

然后一定要放弃合法的-不合法的这种想法,应该改成0不合法-1不合法+2不合法-3不合法。。。

然后快速幂还没取模了,exlucas的快速幂还算错了次方

码:

#include<iostream>
#include<cstdio>
using namespace std;
#define ll long long
ll TREE,x,y,a[9999],P[9999],p[9999],T,cnt,lin,i,m2,n,n2,n1,m,b[99];
void exgcd(ll a,ll b)
{
if(!b)
{
x=1;y=0;return ;
}
exgcd(b,a%b);
ll t=x;
x=y;
y=t-(a/b)*y;
}
ll ksm(ll a,ll b,ll c)
{
ll ans=1;
while(b)
{
if(b&1)ans=a*ans%c;
b/=2;
a=a*a%c;
}
return ans;
}
ll CRT()
{
int i;
ll daan=0;
for(i=1;i<=cnt;i++)
{
ll mi=TREE/P[i];
exgcd(mi,P[i]);
daan=(daan+x*a[i]%TREE*mi%TREE)%TREE;
}
if(daan<0)daan+=TREE;
return daan;
}
struct la
{
ll gs,ans;
};
la exlucas(ll n,int xh)
{
ll ls=n/p[xh],ys=n%P[xh],i;
la o;
o.ans=1;
o.gs=ls;
if(n==0)return o;
if(n>=P[xh]) for(i=1;i<=P[xh];i++)
{
if(i%p[xh]==0)continue;
o.ans*=i;
o.ans%=P[xh];
}
o.ans=ksm(o.ans,n/P[xh],P[xh]);
for(i=1;i<=ys;i++)
{
if(i%p[xh]==0)continue;
o.ans*=i;
o.ans%=P[xh];
}
la nd=exlucas(ls,xh);
o.gs+=nd.gs;
o.ans=o.ans*nd.ans%P[xh];
return o;
}
ll C(ll n,ll m)
{
if(n<0||n>m)return 0;
int i,ms;
for(ms=1;ms<=cnt;ms++)
{
a[ms]=1;
la fz=exlucas(m,ms);
la fm1=exlucas(n,ms);
la fm2=exlucas(m-n,ms);
fz.gs-=fm1.gs+fm2.gs;
exgcd(fm1.ans,P[ms]);
fz.ans=fz.ans*x%P[ms];
exgcd(fm2.ans,P[ms]);
fz.ans=fz.ans*x%P[ms];
a[ms]=fz.ans*ksm(p[ms],fz.gs,P[ms])%P[ms];
if(a[ms]<0)a[ms]+=P[ms];
}
return CRT();
} ll daan=0;
int jishu=0;
void dfs(ll m2,ll wz)
{
if(wz==n1+1)
{
if(jishu&1)
{
daan-=C(n-1,m2-1);
daan%=TREE;
} else daan+=C(n-1,m2-1),daan%=TREE;
return ;
}
jishu++;
dfs(m2-b[wz],wz+1);
jishu--;
dfs(m2,wz+1);
}
int main()
{
scanf("%lld%lld",&T,&TREE);
lin=TREE;
for(i=2;i*i<=lin;i++)
{
if(lin%i==0)P[++cnt]=1,p[cnt]=i;
while(lin%i==0)lin/=i,P[cnt]*=i;
}
if(lin!=1)P[++cnt]=p[cnt]=lin;
while(T--)
{
daan=0;
scanf("%lld%lld%lld%lld",&n,&n1,&n2,&m);
m2=m;
for(i=1;i<=n1;i++)
scanf("%lld",&b[i]);
for(i=1;i<=n2;i++)
scanf("%lld",&x),m-=(x-1),m2-=(x-1);
dfs(m,1);
printf("%lld\n",(daan+TREE)%TREE);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: