【题解】 bzoj4004: [JLOI2015]装备购买 (线性基)

bzoj4004,戳我戳我

Solution:

  • 裸的线性基,这没啥好说的,我们说说有意思的地方(就是我老是wa的地方)

Attention:

  • 这题在\(luogu\),上貌似不卡精度,\(bzoj\)卡精度(一开始还以为自己精度被卡的很惨,结果是线性基打错了)
  • 线性基板子:
    for(int j=50;j>=0;j--){
      if(!(box>>j))continue;
      if(!a[j]){a[j]=box;break;}
      else box=(a[j]^box);
    }
  • 注意不是一个个动态开位置存线性基,而是像高斯消元一样存一个倒三角
  • 然后我们要注意的就是线性基的制作方式,这道题表达意思是要前面存在过的装备组合相加得到,那么我们消元的时候是拿存在的线性基的倍数消元
    是这个样子:
double X=eqt[num].a[i]/x[i][i];
    for(int j=i;j<=m;j++){
    eqt[num].a[j]-=(x[i][j]*X);
}

不是这个样子(他和高斯小消元还是有点小不同(我觉得可能是我的高斯消元板子写错了)

double X=x[i][i]/eqt[num].a[i];
    for(int j=i;j<=m;j++){
        eqt[num].a[j]*=X;
        eqt[num].a[j]-=x[i][j];
    }

Code:

//It is coded by Ning_Mew on 5.27
#include<bits/stdc++.h>
#define double long double
using namespace std;

const int maxn=507;
const double eps=1e-5;

int n,m,ans=0,sum=0;
struct Node{
  double a[maxn];int val;
}eqt[maxn];
double x[maxn][maxn];

bool cmp(const Node &xx,const Node &yy){return xx.val<yy.val;}
double ffabs(double xx){return xx<0?-xx:xx;}
bool par(int num){
  bool kk=false; 
  for(int i=1;i<=m;i++){
    if(fabs(eqt[num].a[i])<eps)continue;
    if(fabs(x[i][i])<eps){
      for(int j=i;j<=m;j++){x[i][j]=eqt[num].a[j];}
      kk=true;break;
    }else{
      /*double X=x[i][i]/eqt[num].a[i];
      for(int j=i;j<=m;j++){
	eqt[num].a[j]*=X;
	eqt[num].a[j]-=x[i][j];
	}*/
      double X=eqt[num].a[i]/x[i][i];
      for(int j=i;j<=m;j++){
	eqt[num].a[j]-=(x[i][j]*X);
      }
    }
  }
  return kk;
}
int main(){
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;i++){
    for(int j=1;j<=m;j++){
      scanf("%Lf",&eqt[i].a[j]);
    }
  }
  for(int i=1;i<=n;i++)scanf("%d",&eqt[i].val);

  sort(eqt+1,eqt+n+1,cmp);
  
  for(int i=1;i<=n;i++){
    if(par(i))ans+=eqt[i].val,sum++;
  }
  printf("%d %d\n",sum,ans);
  return 0;
}

posted @ 2018-05-28 23:06  Ning_Mew  阅读(157)  评论(0编辑  收藏  举报