一开始想的:我们可以发现点x的颜色只由1到x的方案数的奇偶性决定,奇数为1,偶数为0
可以用组合数求方案数,二维的情况是C
x
x
+
y
^{x+y}_{x}
xx+y,直接统计2因子出现次数,但这个不能满分
正确的:
若对于任意位都最多只有⼀个xi在这⼀位上为1,那么对于任意维度⼦子集s属于n,有sum(xk)=xk,所以每个因⼦子都是奇数。 有了了这个条件就可以数位DP了了,记录当前位置和每⼀维是否到达上界,枚举当前位的1在哪⼀位上或者没有 .
#include<bits/stdc++.h>
#define rep(i,s,t) for(register int i=s;i<=t;++i)
#define _rep(i,s,t) for(register int i=s;i>=t;--i)
using namespace std;
const int mod=990804011;
inline void inc(int &x,int y)
{
x+=y;
if(x>=mod)
x-=mod;
if(x<0)
x+=mod;
}
typedef long long ll;
int n,m,T,ans;
ll l[10],r[10],x[10];
int f[52][1<<10];
inline int solve(int S)
{
rep(i,0,n-1)
x[i]=(S>>i&1)?(l[i]-1):r[i];
rep(i,0,n-1)
if(x[i]<0)
return 0;
memset(f,0,sizeof f);
f[51][0]=1;
_rep(i,50,0)
{
rep(s,0,(1<<n)-1)
{
if(!f[i+1][s])
continue;
int t=0;
rep(j,0,n-1)
if(x[j]>>i&1)
t|=(1<<j);
inc(f[i][s|t],1ll*(__builtin_popcount(s)+1)*f[i+1][s]%mod);
rep(j,0,n-1)
if((t&(~s))>>j&1)
inc(f[i][s|(t^(1<<j))],f[i+1][s]);
}
}
int ans=0;
rep(s,0,(1<<n)-1)
inc(ans,f[0][s]);
return ans;
}
int main()
{
scanf("%d",&T);
for(;T--;)
{
ans=0;
scanf("%d",&n);
rep(i,0,n-1)
scanf("%lld%lld",l+i,r+i),--l[i],--r[i];
rep(i,0,(1<<n)-1)
__builtin_popcount(i)&1?inc(ans,mod-solve(i)):inc(ans,solve(i));
printf("%d\n",ans);
}
return 0;
}