JZOJ 4245. 【五校联考6day2】er


题目:

传送门


题意:

给出 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(ab)==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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值