记录编号 399369 评测结果 AAAAAAAAAA
题目名称 2672.[HAOI 2017]方案数 最终得分 100
用户昵称 FoolMike 是否通过 通过
代码语言 C++ 运行时间 0.108 s
提交时间 2017-04-26 12:53:24 内存使用 9.73 MiB
显示代码纯文本
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=110,O=1e4+10,p=119<<23|1;
struct pt{ll x,y,z;}P[O];
ll n,m,r;int o,size;
bool OK(ll &s,ll &t){return (s&t)==s;}
bool cmp(const pt &a,const pt &b){
	if (a.x!=b.x) return a.x<b.x;
	if (a.y!=b.y) return a.y<b.y;
	return a.z<b.z;
}
//dp[i][j]表示取i位,用了j次的方案数 
int dp[N][N],C[1010][1010];
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 mul(int x,int y){return (ll)x*y%p;}
void init(){
	for (int i=0;i<1010;i++){
		C[i][0]=1;
		for (int j=1;j<=i;j++) C[i][j]=inc(C[i-1][j-1],C[i-1][j]);
	}
	dp[0][0]=1;
	for (int i=0;i<=64;i++)
	for (int j=0;j<=64;j++)
	for (int k=1;i+k<=64;k++)
		dp[i+k][j+1]=inc(dp[i+k][j+1],mul(dp[i][j],C[i+k][i]));
}
int cnt(ll x){
	int ans=0;
	for (;x;x-=x&-x) ans++;
	return ans;
}
int v[N][N][N],cx[O],cy[O],cz[O];
int val(int a,int b,int c){
	//int a=cnt(x),b=cnt(y),c=cnt(z);
	if (a<b) swap(a,b);
	if (a<c) swap(a,c);
	if (b<c) swap(b,c); 
	if (v[a][b][c]) return v[a][b][c];
	int ans=0;
	for (int i=0;i<=a;i++)
	for (int j=0;j<=b;j++)
	for (int k=0;k<=c;k++)
		ans=inc(ans,mul(mul(dp[a][i],mul(dp[b][j],dp[c][k])),mul(C[i+j+k][k],C[i+j][j])));
	return v[a][b][c]=ans;
}
int DP[2][O],*x=DP[0],*y=DP[1];
int work(int p,int la){
	//printf("%d %d\n",p,la);
	if (p>size) return val(cnt(n)-cx[la],cnt(m)-cy[la],cnt(r)-cz[la]);
	int ans=work(p+1,la);
	if (OK(P[la].x,P[p].x)&&OK(P[la].y,P[p].y)&&OK(P[la].z,P[p].z))
		ans=dec(ans,mul(work(p+1,p),val(cx[p]-cx[la],cy[p]-cy[la],cz[p]-cz[la])));
	return ans;
}
int main()
{
	freopen("problema.in","r",stdin);
	freopen("problema.out","w",stdout);
	scanf("%lld%lld%lld",&n,&m,&r);
	scanf("%d",&o);
	for (int i=1;i<=o;i++){
		ll x,y,z;
		scanf("%lld%lld%lld",&x,&y,&z);
		if (OK(x,n)&&OK(y,m)&&OK(z,r)) P[++size]=(pt){x,y,z};
	}
	sort(P+1,P+size+1,cmp);
	for (int i=1;i<=size;i++){
		cx[i]=cnt(P[i].x);
		cy[i]=cnt(P[i].y);
		cz[i]=cnt(P[i].z);
	}
	init();
	//printf("%d\n",work(1,0));
	cx[size+1]=cnt(n);
	cy[size+1]=cnt(m);
	cz[size+1]=cnt(r);
	for (int la=0;la<=size;la++)
		x[la]=val(cx[size+1]-cx[la],cy[size+1]-cy[la],cz[size+1]-cz[la]);
	for (int p=size;p;p--,swap(x,y))
	for (int la=0;la<p;la++){
		y[la]=x[la];
		if (OK(P[la].x,P[p].x)&&OK(P[la].y,P[p].y)&&OK(P[la].z,P[p].z))
			y[la]=dec(y[la],mul(val(cx[p]-cx[la],cy[p]-cy[la],cz[p]-cz[la]),x[p]));
	}
	printf("%d\n",x[0]);
	return 0;
}