Meet in Middle暴力过了…
正解挖个坑,可能永远不会填了把…
把9维坐标分成前4维和后5维
令
fi,j,k
表示前4维为
i
,后5维与
这样预处理下,然后再枚举一遍就好了
复杂度应该是
反正常数巨大
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
bool bg;
int n,m;
int a[200010][11];
int d[1310][30][310];
int b[1310];
int dis[1310][4310];
ll ans[60];
bool ed;
inline int DIS(int x,int y){
int ret=0;
while(x || y){
ret+=abs(x%4-y%4);
x/=4; y/=4;
}
return ret;
}
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline void rea(int &x){
char c=nc(); x=0;
for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}
int cur[200010],nxt[200010];
void PutAns(ll x){
if(x>=10) PutAns(x/10);
putchar(x%10+'0');
}
int main(){
rea(n); rea(m);
for(int i=0;i<=1024;i++)
for(int j=i+1;j<=1024;j++)
dis[i][j]=dis[j][i]=DIS(i,j);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++) rea(a[i][j]);
for(int k=1;k<=4 && k<=m;k++) cur[i]=cur[i]*4+a[i][k];
for(int k=5;k<=m;k++) nxt[i]=nxt[i]*4+a[i][k];
}
if(m<=4){
for(int i=1;i<=n;i++){
b[cur[i]]++;
}
for(int i=1;i<=n;i++){
for(int j=0;j<(1<<(2*m));j++)
ans[dis[j][cur[i]]]+=b[j];
}
for(int i=0;i<=3*m;i++) printf("%lld ",ans[i]);
return 0;
}
int size=1<<(2*(m-4));
for(int j=0;j<=size;j++){
int (*D)[310]=d[j],*DD=dis[j];
for(int i=1;i<=n;i++){
D[DD[nxt[i]]][cur[i]]++;
}
}
size=1<<8;
for(int i=1;i<=n;i++){
int c=cur[i],nx=nxt[i],*dd=dis[c];
for(int k=0;k<=15;k++){
int *DD=d[nx][k],*D=dd;
for(int j=1;j<=size;j+=16){
ans[k+*(D++)]+=*(DD++);
ans[k+*(D++)]+=*(DD++);
ans[k+*(D++)]+=*(DD++);
ans[k+*(D++)]+=*(DD++);
ans[k+*(D++)]+=*(DD++);
ans[k+*(D++)]+=*(DD++);
ans[k+*(D++)]+=*(DD++);
ans[k+*(D++)]+=*(DD++);
ans[k+*(D++)]+=*(DD++);
ans[k+*(D++)]+=*(DD++);
ans[k+*(D++)]+=*(DD++);
ans[k+*(D++)]+=*(DD++);
ans[k+*(D++)]+=*(DD++);
ans[k+*(D++)]+=*(DD++);
ans[k+*(D++)]+=*(DD++);
ans[k+*(D++)]+=*(DD++);
}
}
}
for(int i=0;i<=3*m;i++) PutAns(ans[i]),putchar(' ');
//printf("\n%d\n",(&ed-&bg)/1024/1024);
return 0;
}