题目:
题意:
给出 n n n种符文的信息,求在使用了 k k k个的情况下威力值最大可以是多少
分析:
一开始小编看到可以乘
2000
2000
2000,马上想到高精度,但这可是涉及到自然对数呀,用高精度整个代码不会烂掉?
后来受到wyc大爷的提示后想起一个关于自然对数的性质:
l
o
g
(
a
∗
b
)
=
=
l
o
g
(
a
)
+
l
o
g
(
b
)
log(a*b)==log(a)+log(b)
log(a∗b)==log(a)+log(b)
然后我就爽快的打起了
d
f
s
dfs
dfs,结果十个点全部
T
T
T飞
.
.
..
..
其实正解用贪心,而对于
n
=
=
2
n==2
n==2时,用
d
p
dp
dp来判断一下是否合法就可以了
代码:
#pragma GCC optimize(2)
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#include<deque>
#include<set>
#define LL long long
using namespace std;
inline LL read(){
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
return d*f;
}
int cy,i,x,y,l2,l1,n,m,k,v[3],ma;
long long su,sum[105],a[105],b[105],f[200000];
double ans,a1,a2,a3,mul[105];
bool cmp(int x,int y) {return x>y;}
int main ()
{
n=read();m=read();k=read();
for(int i=1;i<=n;i++) v[i]=read();
for(int i=1;i<=m;i++)
{
x=read();y=read();
if (x==1) cy=y;
else if (x==2) a[++l1]=y;
else b[++l2]=y;
}
sort(a+1,a+l1+1,cmp);
sum[0]=0;
for(int i=1;i<=l1;i++) sum[i]=sum[i-1]+a[i];
ma=sum[l1];
sort(b+1,b+l2+1,cmp);
mul[0]=0;
for(int i=1;i<=l2;i++) mul[i]=mul[i-1]+log(b[i]*1.0);
if (n==1)
{
for(int i=0;i<=l1;i++)
{
if (i>k) break;
ans=max(ans,log(1.0*(sum[i]+v[1]))+mul[k-i]);
ans=max(ans,log(1.0*(cy+sum[i]))+mul[k-i-1]);
}
return !printf("%.3lf",ans);
}
else
{
mul[0]=1;f[0]=1;
for(int i=0;i<=l1;i++)
{
if (i>k) break;
for(int j=ma;j>=sum[i]-sum[i-1];j--) f[j]=max(f[j],f[j-sum[i]+sum[i-1]]);
for(int j=0;j<=sum[i];j++)
if(f[j]>0&&f[sum[i]-j]>0)
{
su=sum[i]-j;
ans=max(ans,log((su+v[1])*1.0)+log((j+v[2])*1.0)+mul[k-i]);
ans=max(ans,log((su+v[1])*1.0)+log((j+cy)*1.0)+mul[k-i-1]);
ans=max(ans,log((su+cy)*1.0)+log((j+v[2])*1.0)+mul[k-i-1]);
}
}
}
printf("%.3lf",ans);
return 0;
}