给定方程
X1+X2+. +Xn=M
我们对第l..N1个变量进行一些限制:
Xl < = A
X2 < = A2
Xn1 < = An1
我们对第n1 + 1..n1+n2个变量进行一些限制:
Xn1+l > = An1+1
Xn1+2 > = An1+2
Xnl+n2 > = Anl+n2
求:在满足这些限制的前提下,该方程正整数解的个数。
答案可能很大,请输出对p取模后的答案,也即答案除以p的余数。
给定方程
X1+X2+. +Xn=M
我们对第l..N1个变量进行一些限制:
Xl < = A
X2 < = A2
Xn1 < = An1
我们对第n1 + 1..n1+n2个变量进行一些限制:
Xn1+l > = An1+1
Xn1+2 > = An1+2
Xnl+n2 > = Anl+n2
求:在满足这些限制的前提下,该方程正整数解的个数。
答案可能很大,请输出对p取模后的答案,也即答案除以p的余数。
输入含有多组数据,第一行两个正整数T,p。T表示这个测试点内的数据组数,p的含义见题目描述。
对于每组数据,第一行四个非负整数n,n1,n2,m。
第二行nl+n2个正整数,表示A1..n1+n2。请注意,如果n1+n2等于0,那么这一行会成为一个空行。
共T行,每行一个正整数表示取模后的答案。
n < = 10^9 , n1 < = 8 , n2 < = 8 , m < = 10^9 ,p<=437367875
对于l00%的测试数据: T < = 5,1 < = A1..n1_n2 < = m,n1+n2 < = n
题解: 对于an1+1~an2这些数,给m减去ai-1就没有影响了,因为限制是Xi>=ai,而插板法的限制是Xi>=1,所以直接减去ai-1就能消除影响
对于a1~an1这些数,只有8个,可以容斥,所有情况-1个不满足的+2个不满足的-...
这里不满足就是强制某些数>ai,也就是给m减去ai,然后用组合数求解。
组合数取模用lucas+中国剩余定理来做就可以了,参见bzoj 2142
#include
#include
#include
#include
#include
#define N 200003
#define LL long long
#define pa pair
using namespace std;
LL n,m,p;
LL prime[N],cnt[N],mod[N],a[N],a1[N],ans1,ans;
int t,n1,n2,tot,q[N],len;
void get_prime()
{
LL x=p;
for (LL i=2;i*i<=x;i++)
if (x%i==0)
{
prime[++tot]=i; cnt[tot]=0; mod[tot]=1;
while (x%i==0)
{
x/=i;
cnt[tot]++;
mod[tot]*=i;
}
}
if (x>1)
{
prime[++tot]=x;
cnt[tot]=1;
mod[tot]=x;
}
}
int quickpow(LL num,LL x,LL m)
{
LL ans=1; LL base=num%m;
while(x)
{
if (x&1) ans=(ans*base)%m;
x>>=1;
base=(base*base)%m;
}
return ans%m;
}
void exgcd(LL a,LL b,LL &x,LL &y)
{
if (b==0)
{
x=1; y=0;
return;
}
exgcd(b,a%b,x,y);
LL t=y;
y=x-(a/b)*y;
x=t;
}
LL inverse(LL a,LL b)
{
LL x,y;
exgcd(a,b,x,y);
return (x%b+b)%b;
}
pa solve(int k,LL n)
{
if (n==0) return pa(0,1);
LL x=n/prime[k]; LL y=n/mod[k];
LL ans=1;
if (y)
{
for (LL i=2;i