蓝桥杯算法训练审美课

#include <bits/stdc++.h>
using namespace std;
//用位存,比较的时候直接取反看是否相等,不要异或
//这是我的做法,超时了,
//其实他用的是取反的技巧避免了第二重循环,那么就判断去饭后的结果在不在就可以了,用hash加速
// int n,m,a[50000],cache[50000];//cache 0 1
// int main(){
//     cin>>n>>m;
//     memset(a,0,sizeof(a));
//     memset(cache,0,sizeof(cache));
//     int map=(1<<m)-1,s=0;
//     // cout<<map<<endl;   
//     for(int i=0;i<n;i++){
//         int k;
//         for(int j=0;j<m;j++){
//             cin>>k;
//             a[i]=(a[i]<<1)+k;
//         }
//     }
//     // for(int i=0;i<n;i++){cout<<a[i]<<" ";}
//     // cout<<endl;
//     for(int i=0;i<n;i++){
//         int temp=0,other=0,num=0;
//         //other 是累计减少
//         if(cache[i]==1) continue;
//         for(int j=i+1;j<n;j++){
//             // cout<<a[i]<<" "<<a[j]<<" "<<(a[i]^a[j])<<endl;
//             int r=a[i]^a[j];
//             if(r==map) temp++;//注意!!!异或运算符优先级低,要打括号。
//             //temp得到的是a[i+1]--a[j-1],即在相同之前的所有不同数
//             else if(r==0){
//                 //说明a[j]和a[i]一样
//                 other+=temp;
//                 num++;
//                 cache[j]=1;
//             } 
//         }
//         temp=temp*(num+1)-other;
//         s+=temp;
//     }
//     cout<<s<<endl;
//     return 0;
// }

//ans 为 对应的二进制转化后的值的个数
//把 On2 变成 On 了。。
int a[50000],ans[2000000],m,n;
int main(){
    cin>>n>>m;
    memset(a,0,sizeof(a));
    memset(ans,0,sizeof(ans));
    int map=(1<<m)-1,s=0;
    // cout<<map<<endl; 
    for(int i=0;i<n;i++){
        int k;
        for(int j=0;j<m;j++){
            cin>>k;
            a[i]=(a[i]<<1)+k;
        }
        ans[a[i]]++;
    }
    for(int i=0;i<n;i++){
        int k=a[i]^map;//相当于取反
        s+=ans[k];
        // int k=(~a[i]);这么做不可以,因为取反是针对于int全位的,
        // s+=ans[k];
        //对 a[i] 取反后直接找对应的数目
    }
    //这么做可以保证 1 2、 2 1都计算,所以除2
    //我的方法中不能保证
    cout<<s/2<<endl;
    return 0;
}

 

posted @ 2020-06-06 21:52  西伯利亚挖土豆  阅读(110)  评论(0编辑  收藏  举报