【luogu3734】 [HAOI2017]方案数 组合计数
code:
#include <cstdio> #include <string> #include <cstring> #include <algorithm> #define N 66 #define ll long long #define mod 998244353 using namespace std; ll lowbit(ll t) { return t&(-t); } int count(ll x) { int tmp=0; for(;x;x-=lowbit(x)) ++tmp; return tmp; } struct node { ll x,y,z; }p[100007]; bool cmp(node a,node b) { return (a.x==b.x&&a.y==b.y)?(a.z<b.z):(a.x==b.x?a.y<b.y:a.x<b.x);} ll n,m,r; int f[N][N][N],C[N][N],g[100007]; void setIO(string s) { freopen((s+".in").c_str(),"r",stdin); } int main() { // setIO("input"); int i,j,o; scanf("%lld%lld%lld%d",&n,&m,&r,&o); for(i=1;i<=o;++i) scanf("%lld%lld%lld",&p[i].x,&p[i].y,&p[i].z); ++o; p[o].x=n,p[o].y=m,p[o].z=r; sort(p+1,p+1+o,cmp); f[0][0][0]=1,C[0][0]=1; for(i=1;i<=64;++i) { C[i][0]=1; for(j=1;j<=i;++j) C[i][j]=(ll)(C[i-1][j]+C[i-1][j-1])%mod; } for(i=0;i<=64;++i) { for(j=0;j<=64;++j) { for(int k=0;k<=64;++k) { if(i) { for(int l=1;l<=i;++l) f[i][j][k]=(ll)(f[i][j][k]+(ll)f[i-l][j][k]*C[i][l]%mod)%mod; } if(j) { for(int l=1;l<=j;++l) f[i][j][k]=(ll)(f[i][j][k]+(ll)f[i][j-l][k]*C[j][l]%mod)%mod; } if(k) { for(int l=1;l<=k;++l) f[i][j][k]=(ll)(f[i][j][k]+(ll)f[i][j][k-l]*C[k][l]%mod)%mod; } } } } for(i=1;i<=o;++i) { ll x=p[i].x,y=p[i].y,z=p[i].z; g[i]=f[count(x)][count(y)][count(z)]; for(j=1;j<i;++j) { ll x1=p[j].x,y1=p[j].y,z1=p[j].z; if((x1&x)!=x1||(y1&y)!=y1||(z1&z)!=z1) continue; int bx=count(x^x1),by=count(y^y1),bz=count(z^z1); g[i]=(ll)((ll)(g[i]-(ll)g[j]*f[bx][by][bz]%mod)+mod)%mod; } } printf("%d\n",g[o]); return 0; }