zoukankan      html  css  js  c++  java
  • 蓝桥杯 试题 算法训练 审美课

    资源限制
    时间限制:1.0s 内存限制:256.0MB


    问题描述

      《审美的历程》课上有n位学生,帅老师展示了m幅画,其中有些是梵高的作品,另外的都出自五岁小朋友之手。老师请同学们分辨哪些画的作者是梵高,但是老师自己并没有答案,因为这些画看上去都像是小朋友画的……老师只想知道,有多少对同学给出的答案完全相反,这样他就可以用这个数据去揭穿披着皇帝新衣的抽象艺术了(支持帅老师^_^)。
      答案完全相反是指对每一幅画的判断都相反。


    输入格式

      第一行两个数n和m,表示学生数和图画数;
      接下来是一个n*m的01矩阵A:
      如果aij=0,表示学生i觉得第j幅画是小朋友画的;
      如果aij=1,表示学生i觉得第j幅画是梵高画的。


    输出格式

      输出一个数ans:表示有多少对同学的答案完全相反。


    样例输入

      3 2
      1 0
      0 1
      1 0


    样例输出

      2


    样例说明

      同学1和同学2的答案完全相反;
      同学2和同学3的答案完全相反;
      所以答案是2。


    数据规模和约定

      对于50%的数据:n<=1000;
      对于80%的数据:n<=10000;
      对于100%的数据:n<=50000,m<=20。


    暴力法只能获得70分。需要用map存储数据,并将学生的答案处理为二进制数(异或取反)或字符串。

    1、二进制数(异或取反)

    #include<iostream>
    #include<map>
    using namespace std;
    
    int main()
    {
        map<int,int>a; //用map存储数据,it->first表示将n位学生的答案视为二进制数以十进制数存储,it->second表示该种答案的相同个数
        int n,m;
        cin>>n>>m;
        for(int i=0;i<n;i++)
        {
            int num=0;
            int x;
            for(int j=0;j<m;j++)
            {
                cin>>x;
                num=(num<<1)+x;
            }
            a[num]++;
        }
        int sum=0,maxn=(1<<m)-1,mid=maxn/2; //maxn为m位全为1的二进制数 
        for(map<int,int>::iterator it=a.begin();it!=a.end();it++)
        {
            int x=it->first;
            if(x>mid) //[0,mid]中的任意一个数x与maxn进行异或运算的值一定在(mid,maxn]中,所以遍历0-maxn/2即可(map默认按key值从小到大排序) 
            {
                break;
            }
            int num=x^maxn; //与maxn进行异或运算即可取反 
            sum+=a[num]*it->second; //当前答案取反的相同个数*当前答案的相同个数
        }
        cout<<sum<<endl;
        return 0;
    }

    2、字符串

    #include<iostream>
    #include<map>
    using namespace std;
    
    int main()
    {
        map<string,int>num; //用map存储数据,it->first表示n位学生答案的字符串形式,it->second表示该种答案的相同个数 
        int m,n;
        cin>>n>>m;
        for(int i=0;i<n;i++)
        {
            string s="";
            char x;
            for(int j=0;j<m;j++)
            {
                cin>>x;
                s+=x;
            }
            num[s]++;
        }
        int sum=0;
        for(map<string,int>::iterator it=num.begin();it!=num.end();it++)
        {
            string s="";
            for(int i=0;i<m;i++)
            {
                if(it->first[i]=='0')
                    s+='1';
                else
                    s+='0';
            } //将答案取反 
            sum+=num[s]*it->second; //当前答案取反的相同个数*当前答案的相同个数
        }
        cout<<sum/2<<endl; //重复计算了所以除以2
        return 0;
    }
  • 相关阅读:
    DOM操作之获取HTML、文本和值
    DOM操作之属性和样式操作
    DOM节点的增删改查
    其他选择器
    属性过滤选择器
    Linux
    Linux
    Appium自动化(3)
    Appium自动化(2)
    Appium自动化(1)
  • 原文地址:https://www.cnblogs.com/love-ziji/p/13419637.html
Copyright © 2011-2022 走看看