考虑计算方案数,令
xi=ai−li(0≤xi≤ri−li)
,得到
∑l1+x1?∑r2−x2∑x1+∑x2?∑r2−∑l1
x1 和 x2 并没有本质差别,用插板法解决。取等号时可以直接算,取小于等于时可以加入一个元素来放置多出来的部分。上限用容斥来解决。
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
const int maxn=20,p=1000000007;
int l1[maxn],l2[maxn],r1[maxn],r2[maxn],f[maxn],fac[maxn+10],inv[maxn+10],n1,n2,n;
int inc(int x,int y)
{
x+=y;
return x>=p?x-p:x;
}
int dec(int x,int y)
{
x-=y;
return x<0?x+p:x;
}
int pow(int b,int k)
{
int r=1;
for (;k;k>>=1,b=(LL)b*b%p)
if (k&1) r=(LL)r*b%p;
return r;
}
int get(int n,int m)
{
int ret=1;
for (int i=n+m-1;i>=n+1;i--) ret=(LL)ret*i%p;
ret=(LL)ret*inv[m-1]%p;
return ret;
}
int calc(int n,int s)
{
int ret=0,s1,cnt,x;
for (int S=0;S<(1<<n);S++)
{
cnt=0;
s1=s;
for (int i=0;i<n;i++)
if (S&(1<<i))
{
cnt++;
s1-=f[i]+1;
}
if (s1<0) continue;
x=get(s1,n);
if (cnt&1) ret=dec(ret,x);
else ret=inc(ret,x);
}
return ret;
}
void solve()
{
int x,y,z,w,s=1;
scanf("%d",&n1);
for (int i=1;i<=n1;i++) scanf("%d%d",&l1[i],&r1[i]);
scanf("%d",&n2);
for (int i=1;i<=n2;i++) scanf("%d%d",&l2[i],&r2[i]);
n=n1+n2;
w=0;
for (int i=1;i<=n1;i++) w=dec(w,l1[i]);
for (int i=1;i<=n2;i++) w=inc(w,r2[i]);
for (int i=1;i<=n1;i++) f[i-1]=r1[i]-l1[i];
for (int i=1;i<=n2;i++) f[i+n1-1]=r2[i]-l2[i];
y=calc(n,w);
f[n]=w;
x=calc(n+1,w);
for (int i=0;i<n;i++) s=(LL)s*(f[i]+1)%p;
z=dec(s,x);
x=dec(x,y);
s=pow(s,p-2);
x=(LL)x*s%p;
y=(LL)y*s%p;
z=(LL)z*s%p;
printf("%d %d %d\n",z,y,x);
}
int main()
{
//freopen("a.in","r",stdin);
fac[0]=1;
for (int i=1;i<=maxn;i++) fac[i]=(LL)fac[i-1]*i%p;
for (int i=0;i<=maxn;i++) inv[i]=pow(fac[i],p-2);
int T;
scanf("%d",&T);
while (T--) solve();
}