oldssoj2677

来源:互联网 发布:vb winhttp 编辑:程序博客网 时间:2024/06/05 02:10

JRY is so rich that he creates an m demensional space and n sight spots inside. Because of special technical problem, all the coordinates are integers between [0,2]. 

The roads in this space are all parallel to the axis, so the distance between two sight spots is their Manhattan distance. More specifically, if the coordinate of one sight spot is (x1,x2,…,xm), and that of another sight spot is (y1,y2,…,ym), then their distance is. JRY wants to establish some bus routes between two sight spots, so he needs to do some research first. 
For you, the problem is to find the total number of pairs (x,y) for each k, that the distance between (x,y) is k. Please be aware: 1. (x,x) does not count; 2. (x,y) and (y,x) are identical, so that it is only one pair; 3. different sight spots may have same coordinates. 

WBS是如此有钱,以至于他创造了一个m维空间,并且在里面放置了n个妹子。但是因为一些奇怪的技术问题,所有妹子的坐标都是[0,2]之间的整数。

因为WBS喜欢笔直的道路,因此空间中所有的路线都是平行于坐标轴的。换句话说,两个妹子之间的距离就是他们的曼哈顿距离。如果两个点的坐标分别是(x1,x2,….,xm),(y1,y2,….,ym),那么他们的距离就是sigm(abs(xi-yi)) i=1..m 。为了方便泡妞,WBS想要在几个妹子之间建立道路,所以首先,他需要进行一些调查。

对于你,对于每个k,你需要找出满足dis(x,y)=k的妹子对数。

你需要注意:

1.(x,x)并不需要统计。

2.(x,y)(y,x)不必重复统计。

3.妹子的坐标可能会重复。

输入

The first line of the input is a single integer T (T=11), indicating the number of testcases. 

For each testcase, the first line contains two integers n and m. Each of the following n lines contains one string of length m, which consists three types of characters 0,1,2, and the j-th character of the i-th string means the j-th coordinate of the i-th spot. It is guaranteed that the m of the i-th testcase is i, and for all testcases ∑n≤300000.

输入的第一行是一个数字T(T=11),表示数据组数。

对于接下来的每一组测试数据,第一行包括两个整数n、m。

接下来的n行,每行一个长度为m的字符串(只包括0、1、2三种字符),第i行的第j个字符表示第i个人的第j个坐标。确保第i组测试数据的m=i。

对于所有的测试数据,∑n≤300000。

输出

For each testcase, print 2m+1 lines. The single number in the i-th line of the output indicates the number of pairs of sight spots with distance i-1

对于每一组测试数据,输出2m+1行,第i行的一个数字表示距离为i-1的点对个数。

样例输入

22 1016 2000110110200

样例输出

01017610
 

#include <iostream>#include <cstring>#include <cstdlib>#include <cstdio>#include <algorithm>#include <cmath>using namespace std;const int maxn=300005;int n,m,f[2][maxn][25],mx,a[maxn]; long long ans;char s[25];inline int get(){    char c;while(!isdigit(c=getchar()));    int v=c-48;while(isdigit(c=getchar()))v=v*10+c-48;    return v;}inline void work(){    int p=1,dis=0,num=0;    int now,lst;    for(int i=1;i<=m;++i){        ++num;dis+=2;        now=num&1,lst=now^1;        memset(f[now],0,sizeof(f[now]));        for(int j=0;j<mx;++j){            int x=j/(p*3);            int rx=x*p*3;            int y=j%p;            int mid=(j-rx-y)/p;            for(int d=0;d<=dis;++d)                for(int k=0;k<=2;++k){                    if(d>=abs(k-mid))                        f[now][j][d]+=f[lst][rx+k*p+y][d-abs(k-mid)];                }        }        p*=3;    }               for(int k=0;k<=dis;++k){        ans=0;        if(k==0) for(int i=1;i<=n;++i) ans+=f[now][a[i]][k]-1;        else for(int i=1;i<=n;++i)ans+=f[now][a[i]][k];        printf("%lld\n",ans>>1);    }}inline int getint(char *c){    int len=strlen(c);    int num=c[0]-48;    for(int i=1;i<len;++i)num=num*3+c[i]-48;    return num;}int main(){    int t=get();    while(t--){        memset(f,0,sizeof(f));        memset(a,0,sizeof(a));        mx=1;n=get();m=get();        for(int i=1;i<=n;++i){            scanf("%s",s);            a[i]=getint(s);            ++f[0][a[i]][0];        }        for(int i=1;i<=m;++i)mx*=3;        work();    }    return 0;}

思路:巧妙地将它转化成三进制来写。状压dp。f[ i ][ j ][ k ]为i维下,距离状态(坐标)j的距离为k的个数。注意优化时间。

评价:好题。



0 0
原创粉丝点击