1. 程式人生 > >【BZOJ4004】[JLOI2015]裝備購買 貪心+高斯消元

【BZOJ4004】[JLOI2015]裝備購買 貪心+高斯消元

屬性 tchar pri getc tput += urn 又是 ron

【BZOJ4004】[JLOI2015]裝備購買

Description

臉哥最近在玩一款神奇的遊戲,這個遊戲裏有 n 件裝備,每件裝備有 m 個屬性,用向量zi(aj ,.....,am) 表示 (1 <= i <= n; 1 <= j <= m),每個裝備需要花費 ci,現在臉哥想買一些裝備,但是臉哥很窮,所以總是盤算著怎樣才能花盡量少的錢買盡量多的裝備。對於臉哥來說,如果一件裝備的屬性能用購買的其他裝備組合出(也就是說臉哥可以利用手上的這些裝備組合出這件裝備的效果),那麽這件裝備就沒有買的必要了。嚴格的定義是,如果臉哥買了 zi1,.....zip這 p 件裝備,那麽對於任意待決定的 zh,不存在 b1,....,bp 使得 b1zi1 + ... + bpzip = zh(b 是實數),那麽臉哥就會買 zh,否則 zh 對臉哥就是無用的了,自然不必購買。舉個例子,z1 =(1; 2; 3);z2 =(3; 4; 5);zh =(2; 3; 4),b1 =1/2,b2 =1/2,就有 b1z1 + b2z2 = zh,那麽如果臉哥買了 z1 和 z2 就不會再買 zh 了。臉哥想要在買下最多數量的裝備的情況下花最少的錢,你能幫他算一下嗎?

Input

第一行兩個數 n;m。接下來 n 行,每行 m 個數,其中第 i 行描述裝備 i 的各項屬性值。接下來一行 n 個數, 其中 ci 表示購買第 i 件裝備的花費。

Output

一行兩個數,第一個數表示能夠購買的最多裝備數量,第二個數表示在購買最多數量的裝備的情況下的最小花費

Sample Input

3 3
1 2 3
3 4 5
2 3 4
1 1 2

Sample Output

2 2

HINT

如題目中描述,選擇裝備 1 裝備 2,裝備 1 裝備 3,裝備 2 裝備 3 均可,但選擇裝備 1 和裝備 2 的花費最小,為 2。對於 100% 的數據, 1 <= n;m <= 500; 0 <= aj <= 1000。

題解

:又是貪心+高斯消元。。。排序就行了。

不過這題求的不是異或意義下的線性基,所以我們可以轉化成模意義下的線性基,方法差不多(就是容易錯啊)。

聽說double也能過。。。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define mod 1000000007
using namespace std;
typedef long long ll;
int n,m,ans,tot;
struct item
{
	ll v[510];
	int cost;
}s[510];
int vis[510];
bool cmp(item a,item b)
{
	return a.cost<b.cost;
}
int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<‘0‘||gc>‘9‘)	{if(gc==‘-‘)f=-f;	gc=getchar();}
	while(gc>=‘0‘&&gc<=‘9‘)	ret=ret*10+gc-‘0‘,gc=getchar();
	return ret*f;
}
ll pm(ll x,ll y)
{
	ll z=1;
	while(y)
	{
		if(y&1)	z=z*x%mod;
		x=x*x%mod,y>>=1;
	}
	return z;
}
int main()
{
	n=rd(),m=rd();
	int i,j,k,l;
	for(i=1;i<=n;i++)	for(j=1;j<=m;j++)	s[i].v[j]=rd();
	for(i=1;i<=n;i++)	s[i].cost=rd();
	sort(s+1,s+n+1,cmp);
	ll t;
	for(i=1;i<=m;i++)
	{
		for(k=0,j=1;j<=n;j++)	if(!vis[j]&&s[j].v[i])
		{
			k=j,vis[j]=1,ans+=s[j].cost;
			break;
		}
		if(!k)	continue;
		tot++;
		t=pm(s[k].v[i],mod-2);
		for(j=i;j<=m;j++)	s[k].v[j]=s[k].v[j]*t%mod;
		for(j=1;j<=n;j++)	if(j!=k&&s[j].v[i])
		{
			t=s[j].v[i];
			for(l=1;l<=m;l++)	s[j].v[l]=(s[j].v[l]-t*s[k].v[l]%mod+mod)%mod;
		}
	}
	printf("%d %d",tot,ans);
	return 0;
}

【BZOJ4004】[JLOI2015]裝備購買 貪心+高斯消元