FJUT ACM 2315 Home_W的位运算2

 

Home_W在离散数学中最新学到了一个新姿势,

若关系向量 A={a1,a2,……,am),B={b1,b2,……,bm); (ai,bi属于集合{0,1})

定义 A*B=(a1&b1)|(a2&b2)|……|(am&bm) 其中&为与运算,|为或运算

若A*B=1 (true)则称A,B之间有关系

现在Home_W希望你帮他找一下,在一组向量里有多少个不同的三角关系

三角关系关系的定义如下

若Ai,Aj,Ak,的下标互不相同且同时满足 Ai*Aj=1,Ai*Ak=1,Aj*Ak=1,则称Ai,Aj,Ak构成三角关系(注意三角关系与顺序无关,即<Ai,Aj,Ak>和<Ak,Aj,Ai>被视为同一个三角关系)

 

Input

第一行是一个整数T代表数据的组数

接下来时T组数据(T<=1000)

每组数据第一行是两个整数 N和M分别代表向量的数量和维数,

接下来N行 代表向量 A1,A2,A3,……,AN

其中每行都有M个数字代表M维向量Ai上 a1,a2,a3,……,aM的值;

M<=30

3<=N<=100;

Output

对于每组数据输出一行,每行有一个整数代表三角关系的个数

SampleInput
2
5 7
1 0 0 0 0 0 1
0 0 0 1 0 1 0
1 0 0 1 1 1 1
1 0 0 0 0 1 1
0 0 1 0 1 0 0
3 11
1 1 1 0 1 0 0 1 0 0 1
0 1 0 0 1 1 1 0 0 0 0
1 1 0 0 0 1 1 0 0 1 1
SampleOutput
2
1

题意如上,
这题看起来题目有点繁琐,但是读懂了题目,第一感觉不难,只要按照题意来求解,至于三角关系,直接o(n^3)的枚举应该就能完成
于是我就愉快的开始怼这一题
 1 #include<stdio.h>
 2 int x[105][35];
 3 int PD(int *x,int *y,int m)
 4 {
 5    int i,num;
 6    num=x[0]&y[0];
 7    for(i=1;i<m;i++)
 8    {
 9        num=num|(x[i]&y[i]);
10    }
11    return num;
12 }
13 int main()
14 {
15     int t,i,n,m,j,z,flag;
16     while(~scanf("%d",&t))
17     {
18         while(t--)
19         {flag=0;
20             scanf("%d%d",&n,&m);
21             for(j=0;j<n;j++)
22                 for(z=0;z<m;z++)
23                 scanf("%d",&x[j][z]);
24             for(i=0;i<n;i++)
25             {
26                 for(j=i+1;j<n;j++)
27                 {
28                     for(z=j+1;z<n;z++)
29                     {
30                     if(PD(x[i],x[j],m)==1&&PD(x[j],x[z],m)==1&&PD(x[i],x[z],m)==1)
31                         flag++;
32                     }
33                 }
34             }
35             printf("%d\n",flag);
36         }
37     }
38     return 0;
39 }

愉快的过了样例后,直接交了一发!

。。。。。。。,我就懵逼了,后来问了CWL学长,CWL学长说PD函数还可以优化!

我就卡住了,后来仔细阅读了题目,

发现

若关系向量 A={a1,a2,……,am),B={b1,b2,……,bm); (ai,bi属于集合{0,1})

定义 A*B=(a1&b1)|(a2&b2)|……|(am&bm) 其中&为与运算,|为或运算

其实这个运算过程就是把集合A看成一个二进制数

把集合B看成一个二进制数

看成a&b

如果a&b不为0,则A*B的结果必为1;

若为0,则A*B的结果必为0;

那思路就很明了了,只要把A,B化成十进制,再进行一次A&B,判断其结果

就可以得出答案了,明显优化了PD的函数!!!

贴上代码

#include<stdio.h>
#include<math.h>
int x[105];
int y[35];
int PD(int a,int b)
{
    if((a&b)!=0)
        return 1;
    else
        return 0;
}
int main()
{
    int t,i,n,flag,m,j,ans,z;
    while(~scanf("%d",&t))
    {
        while(t--)
        {
            scanf("%d%d",&n,&m);
            for(i=0;i<n;i++)
            {
                for(j=0;j<m;j++)
                {
                    scanf("%d",&y[j]);
                }
                ans=0;
                for(j=m-1;j!=-1;j--)
                {
                    ans+=y[j]*(1<<(m-1-j));
                }
                x[i]=ans;
            }
            flag=0;
            for(i=0;i<n;i++)
            {
                for(j=i+1;j<n;j++)
                {
                    for(z=j+1;z<n;z++)
                    {
                        if(PD(x[i],x[j])==1&&PD(x[i],x[z])==1&&PD(x[j],x[z])==1)
                            {flag++;
                            }
                    }
                }
            }
            printf("%d\n",flag);
        }
    }
    return 0;
}

然后发现过了样例,一发ac

但我发现时间还是用得多

然后学长说是函数调用的时间,我就把函数写进main()

里面,再交一次

时间快了1000ms

 

 

posted @ 2018-01-09 15:15  moxin0509  阅读(226)  评论(0编辑  收藏  举报