高斯消元(混合颜料)

来源:互联网 发布:软件图片大全 编辑:程序博客网 时间:2024/03/28 21:12

题目(网易2017内推编程题(二)的第一题)

你就是一个画家!你现在想绘制一幅画,但是你现在没有足够颜色的颜料。为了让问题简单,我们用正整数表示不同颜色的颜料。你知道这幅画需要的n种颜色的颜料,你现在可以去商店购买一些颜料,但是商店不能保证能供应所有颜色的颜料,所以你需要自己混合一些颜料。混合两种不一样的颜色A和颜色B颜料可以产生(A XOR B)这种颜色的颜料(新产生的颜料也可以用作继续混合产生新的颜色,XOR表示异或操作)。本着勤俭节约的精神,你想购买更少的颜料就满足要求,所以兼职程序员的你需要编程来计算出最少需要购买几种颜色的颜料?
输入描述:
第一行为绘制这幅画需要的颜色种数n (1 ≤ n ≤ 50)
第二行为n个数xi(1 ≤ xi ≤ 1,000,000,000),表示需要的各种颜料.

输出描述:
输出最少需要在商店购买的颜料颜色种数,注意可能购买的颜色不一定会使用在画中,只是为了产生新的颜色。

输入例子:
3
1 7 3

输出例子:
3

题解

该题是利用行列式解决异或问题,通过求行列式的秩来求最少需要多少种颜色,没接触过这种题目的同学应该很难将它们联系到一块,不过仔细想想:化简行列式的过程与本题求解的过程,这道题,你上来如果暴力的话,复杂度O(n^3),而且可能会涉及到重复的计算。利用行列式化简(高斯消元)的方法,就是利用到了:7:01113:00112:00101:0001这样的话,7是不可能被异或得出来的,因为他的最高位为1,其他数的最高位为0,而行列式化简,化简成上三角行列式也相同的过程。本题中只涉及到二进制的异或化简,所以利用高斯消元法较为简单。

代码

#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std;int getbit(int x){    int cnt=0;    while(x){        x>>=1;        cnt++;    }    return cnt; } bool cmp(const int& a,const int& b){    return a>b;}int main(){    int n;    while(scanf("%d",&n)!=EOF){        vector<int> v;        int ans=0;        for(int i=0;i<n;i++){            int a;            scanf("%d",&a);            v.push_back(a);        }        while(v.size()>=1){            sort(v.begin(),v.end(),cmp);            if(v[0]==0){                ans+=v.size();                break;            }            vector<int>::iterator it=v.begin();            int fnb=getbit(v[0]);            for(++it;it!=v.end();it++){                if(getbit(*it)==fnb){                    (*it)=(*it)^v[0];                }                else break;            }            v.erase(v.begin());        }        cout<<n-ans<<endl;    }    return 0;}/*151 2 3 4 5 6 7 8 9 10 11 12 13 14 15*/

收获

  1. 熟悉了高斯消元法求解化简行列式,高斯(约当)消元法:就是每次把要消去位上含有最大的元素的行调到最高的地方。
  2. 了解了异或运算与行列式化简的联系。
0 0
原创粉丝点击