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>被视为同一个三角关系)
第一行是一个整数T代表数据的组数
接下来时T组数据(T<=1000)
每组数据第一行是两个整数 N和M分别代表向量的数量和维数,
接下来N行 代表向量 A1,A2,A3,……,AN
其中每行都有M个数字代表M维向量Ai上 a1,a2,a3,……,aM的值;
M<=30
3<=N<=100;
对于每组数据输出一行,每行有一个整数代表三角关系的个数
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
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