标签:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 21
#define pa pair<int,int>
#define mp make_pair
#define fi first
#define se second
using namespace std;
typedef long long ll;
ll a[N];
ll t,p,tot;
ll prime[N],mod[N],num[N],ans[N];
void exgcd(ll a,ll b,ll &x,ll &y,ll &gcd)
{
if(!b)
{
x=1,y=0,gcd=a;
return;
}
exgcd(b,a%b,y,x,gcd);
y=y-a/b*x;
}
ll get_inv(ll n,ll m)
{
ll x,y,gcd;
exgcd(n,m,x,y,gcd);
//(x/gcd%(m/gcd)+m/gcd)%(m/gcd)
//gcd==1
return (x%m+m)%m;
}
ll quick_my(ll x,ll y,ll MOD)
{
ll ret=1;
while(y)
{
if(y&1)ret=(ret*x)%MOD;
x=(x*x)%MOD;
y>>=1;
}
return ret;
}
void getp()
{
int x=p;
for(int i=2;i*i<=x;i++)
{
if(x%i==0)
{
prime[++tot]=i,mod[tot]=1,num[tot]=0;
while(x%i==0)
{
x/=i,mod[tot]*=i,num[tot]++;
}
}
}
if(x!=1)
{
prime[++tot]=x,mod[tot]=x,num[tot]=1;
}
}
ll crt()
{
ll ret=0;
for(int i=1;i<=tot;i++)
{
ret=(ret+p/mod[i]*get_inv(p/mod[i],mod[i])%p*ans[i])%p;
}
return ret;
}
pa get_factor(ll x,ll pri,ll Mod)
{
ll ans=1;
if(x==0||x==1)return mp(0,1);
ll cnt_circle=x/Mod,cnt_pri=x/pri;
if(cnt_circle!=0)
{
for(int i=2;i<Mod;i++)
{
if(i%pri!=0)
ans=(ans*(ll)i)%Mod;
}
ans=quick_my(ans,cnt_circle,Mod);
}
for(int i=cnt_circle*Mod+1;i<=x;i++)
{
if(i%pri!=0)
ans=(ans*(ll)i)%Mod;
}
pa tmp=get_factor(cnt_pri,pri,Mod);
return mp(cnt_pri+tmp.fi,ans*tmp.se%Mod);
}
ll get_C(ll n,ll m,int k)
{
if(m==0)return 1;
pa tmp=get_factor(n,prime[k],mod[k]),tmp1=get_factor(m,prime[k],mod[k]),tmp2=get_factor(n-m,prime[k],mod[k]);
return quick_my(prime[k],tmp.fi-tmp1.fi-tmp2.fi,mod[k])*tmp.se%mod[k]*get_inv(tmp1.se,mod[k])%mod[k]*get_inv(tmp2.se,mod[k])%mod[k];
}
ll calc(ll n,ll m)
{
if(n==m||m==0)return 1;
if(n<m)return 0;
for(int i=1;i<=tot;i++)ans[i]=get_C(n,m,i);
return crt();
}
ll ANS;
ll n,n1,n2,m;
void dfs(int now,ll cnt,ll sum)
{
if(now==n1+1)
{
if(cnt%2==0)ANS=(ANS+calc(m-sum-1,n-1))%p;
else ANS=((ANS-calc(m-sum-1,n-1))%p+p)%p;
return;
}
dfs(now+1,cnt,sum);
dfs(now+1,cnt+1,sum+a[now]);
}
int main()
{
scanf("%lld%lld",&t,&p);
getp();
while(t--)
{
scanf("%lld%lld%lld%lld",&n,&n1,&n2,&m);
for(int i=1;i<=n1;i++)scanf("%lld",&a[i]);
for(int i=1;i<=n2;i++)
{
ll x;
scanf("%lld",&x);
m=m-x+1;
}
if(m<=0){puts("0");continue;}
ANS=0;
dfs(1,0,0);
printf("%lld\n",ANS);
}
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
BZOJ 3129 [Sdoi2013]方程 不定方程解的个数+组合数取模
标签:
原文地址:http://blog.csdn.net/wzq_qwq/article/details/48022461