题解:
考虑本质上是在对超矩形的每个点求从(1,1,…,1)走到这个点的方案数的奇偶性之和。
到
(
x
1
,
x
2
,
…
,
x
k
)
(x_1,x_2,\dots,x_k)
(x1,x2,…,xk)的方案数显然为(所有
x
i
x_i
xi都要-1):
(
∑
i
=
1
k
x
i
)
!
∏
x
i
!
\frac{\left(\sum_{i=1}^k x_{i}\right)!}{\prod x_i!}
∏xi!(∑i=1kxi)!
直接这么做是没有前途的,考虑更原始的式子:
∑
i
=
1
k
(
∑
j
=
i
k
x
j
x
i
)
\sum_{i=1}^k\binom{\sum_{j=i}^k x_j}{x_i}
i=1∑k(xi∑j=ikxj)
我们显然可以任意交换
x
i
x_i
xi的顺序,因此这个式子是奇数,一个必要条件是:
∀
i
̸
=
j
,
(
x
i
+
x
j
x
i
)
=
1
(
m
o
d
2
)
(
x
i
+
x
j
)
&
x
i
=
0
,
x
i
&
x
j
=
0
\forall i\not=j,\binom{x_i+x_j}{x_i}=1\ (\mathrm{mod}\ 2)\\ (x_i+x_j)\&x_i=0,x_i\&x_j=0
∀i̸=j,(xixi+xj)=1 (mod 2)(xi+xj)&xi=0,xi&xj=0
很快就会意识到这个条件是充分的,因为若任意两数二进制交集为空,那么做加法和做或运算没有区别,因此式子有值。
因此结论是:方案数模2有值,当且仅当
∀
j
,
∑
i
=
1
k
x
i
[
j
]
≤
1
\forall j,\sum_{i=1}^kx_i[j]\le1
∀j,∑i=1kxi[j]≤1,也就是每一位至多一个1,这个直接数位dp一下既可以了。
最终关于L可以容斥一下,复杂度
O
(
2
2
k
k
log
R
)
O\left(2^{2k}k\log R\right)
O(22kklogR)
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<b;i++)
#define mod 998244353
#define lint long long
#define N 11
#define LEN 60
using namespace std;
inline int upd(int &x,int y) { return (x+=y)>=mod?x-=mod:0; }
lint up[N],L[N],R[N];int xs[1<<N],a[N][LEN],dp[LEN][1<<N];
inline int getlst(lint x,int *a)
{
int n=0;memset(a,0,sizeof(int)*(LEN));if(!x) return 1;
while(x) a[++n]=x&1,x>>=1;return n;
}
inline int calc(int k)
{
int n=0,all=1<<k,v;rep(i,0,k) if(up[i]<0) return 0;
rep(i,0,k) n=max(n,getlst(up[i],a[i]));
rep(i,0,n+1) memset(dp[i],0,sizeof(int)*all);dp[0][all-1]=1;
rep(i,0,k) for(int j=1;j<=n/2;j++) swap(a[i][j],a[i][n-j+1]);
rep(i,0,n) rep(s,0,all) if((v=dp[i][s]))
{
int t=s;
rep(j,0,k) if(a[j][i+1]&&((s>>j)&1)) t^=1<<j;
upd(dp[i+1][t],v);
rep(j,0,k)
if(!((s>>j)&1)) upd(dp[i+1][t],v);
else if(a[j][i+1]) upd(dp[i+1][t^(1<<j)],v);
}
lint ans=0;rep(s,0,all) ans+=dp[n][s];return (int)(ans%mod);
}
int main()
{
int T;scanf("%d",&T);
while(T--)
{
int k,all;scanf("%d",&k),all=1<<k;lint ans=0ll;
rep(i,0,k) scanf("%lld",&L[i]),L[i]--;
rep(i,0,k) scanf("%lld",&R[i]),R[i]--;
xs[0]=1;rep(i,1,all) xs[i]=-xs[i^(i&-i)];
for(int i=0;i<all;ans+=xs[i]*calc(k),i++)
rep(j,0,k) up[j]=(((i>>j)&1)?L[j]-1:R[j]);
ans%=mod,ans+=mod,ans%=mod,printf("%lld\n",ans);
}
return 0;
}