牛客小白月赛82

牛客小白月赛 82 (A~E)

A

7

B

讨论价格最贵的两种商品

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;

int n;
double x, y;
/* 只有两种优惠券各一张, 用给价格最贵的商品更好, 讨论怎么对两个价格最高的商品使用优惠券 */
void solve(){
    double sum=0;
    cin>>n>>x>>y;
    vector<double> p(n+5);
    for(int i=1; i<=n; i++) cin>>p[i], sum+=p[i];
    sort(p.begin()+1, p.begin()+n+1);
    double t=p[n-1]*(x/100.0)+max(p[n]-y, 0.0);
    t=min(t, max(p[n-1]-y, 0.0)+p[n]*(x/100.0));
    cout<<fixed<<setprecision(11)<<sum-p[n]-p[n-1]+t<<'\n';
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    int T = 1;
    cin >> T;
    while(T --){
        solve();
    }    

    return 0;
} 

C

状态机转移模型

f[i][j] 表示处理到第 i 个字母 , 当前字符串不包含子串 txt 的方案数

j=0 : 结尾字母是 t

j=1 : 结尾字母是 tx

j=2 : 结尾字母是其他字母

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef double db;

/*
    f[i][j] 表示处理到第 i 个字母, 当前字符串不包含子串 txt 的方案数
    f[i][1] 表示结尾是字母 t
    f[i][2] 表示结尾字母是 tx
    f[i][0] 表示结尾字母是其他字母
    状态转移 :
        f[i][1]=f[i-1][1]+f[i-1][0];
        f[i][2]=f[i-1][1]
        f[i][0]=f[i-1][1]*24+f[i-1][2]*25+f[i-1][0]*25
    答案 :
        26^n-f[n][0]-f[in[1]-f[n][2]
*/
int n;
int const N = 2e5+10;
ll const MOD = 998244353;
ll f[N][3]; 

ll ksm(ll a, ll k, ll m){
    ll res=1LL;
    while(k){
        if(k&1) res=(res*a)%m;
        k>>=1;
        a=(a*a)%MOD;
    }
    return res;
}

void init(){
    f[1][1]=1LL, f[1][2]=0, f[1][0]=25;
    for(int i=2; i<=2e5; i++){
        f[i][0]=f[i-1][1]*24LL%MOD+f[i-1][2]*25LL%MOD+f[i-1][0]*25LL%MOD;
        f[i][0]%=MOD;
        f[i][1]=(f[i-1][1]+f[i-1][0])%MOD;
        f[i][2]=f[i-1][1];
    }
}

int main(){
    ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);
    init();

    int T = 1;
    cin >> T;
    while(T --){
        cin>>n;
        ll res=ksm(26LL, n, MOD)-f[n][0]-f[n][1]-f[n][2];
        cout<<(res%MOD+MOD)%MOD<<'\n';
    }    

    return 0;
} 

D

参考题解

#include<bits/stdc++.h>
using namespace std;

int n, a, b, x, y;
int const N = 3e5+10; // ?????
double p[N], p1[N], p2[N]; // pi 保存使用第 i 中优惠券优惠的价格 

void solve(){
	cin>>n>>a>>b>>x>>y;
	for(int i=1;i<=n;i++) cin>>p[i];
	sort(p+1,p+n+1); // 对价格数组升序排序  
	for(int i=1;i<=n;i++){
		p1[i]=p[i]-p[i]*x*0.01;
		p2[i]=p[i]-max(0.0, p[i]-y);
	}
	
	double sum=0, res=0; // 总价 & 优惠价 
	int cnta=0, cntb=0; // 使用的优惠券数量 
	for(int i=1; i<=n; i++) sum += p[i];
	
	
	// 对价格最高的 (a+b) 件使用更省钱优惠券 
	for(int i=n-(a+b)+1; i<=n; i++){  
		if(p1[i]>p2[i]) res+=p1[i], cnta++;
		else res+=p2[i], cntb++;	
	}
	
	vector<double> c=vector<double> (); 
	if(cnta>=a){ // 如果第一种优惠券用超了 
		for(int i=n-(a+b)+1; i<=n; i++) // 在后 (a+b) 件贵的商品中
			if(p1[i]>p2[i]) // 使用了 a 优惠券的商品
				c.push_back(fabs(p2[i]-p1[i])); // 放入更换优惠券后亏了多少钱
        sort(c.begin(), c.end()); 
		
		for(double loss : c){ // 从损失小的开始遍历 
			if(cnta>a){
				cnta --;
				res-=loss; // 亏损的钱 
			}
			else break;
		}
	} 
	
	c.clear();	
	if(cntb>=b){ // 如果第二种优惠券用超了 
		for(int i=n-(a+b)+1; i<=n; i++) // 在后 (a+b) 件贵的商品中
			if(p2[i]>p1[i]) // 使用了 b 优惠券的商品
				c.push_back(fabs(p1[i]-p2[i])); // 放入更换优惠券后亏了多少钱
		sort(c.begin(), c.end()); 
		
		for(double loss : c){ // 从损失小的开始遍历 
			if(cntb>b){
				cntb --;
				res-=loss; // 亏损的钱 
			}
			else break;
		}
	} 
	cout<<fixed<<setprecision(11)<<sum-res<<'\n';
}
int main()
{
	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); 
	int T; cin>>T; 
	while(T--)solve();
	return 0;
}

E

题解 | 牛客小白月赛 82 题解_牛客博客 (nowcoder.net)

考虑最终状态 , 消去的魔法宝石的数量一定有偶数个
如果有连续的魔法宝石被消去消去 , 那么这段连续的魔法宝石数量也为偶数,
并且这里包含的所有普通宝石都可以被消去

f[i][j][k] 表示当前状态对应的最大价值总和 :
i :
当前为第 i 个魔法宝石
j :
当前总花费
k=1 :
  买了第 i 个宝石和第 i-1 个宝石
  k=0 :
    没买第 i 个宝石
    转移 :
    f[i][j][0]=max(f[i-1][j], f[i-1][j][1])
    f[i][j][1]=max(f[i-2][j-wi-wi-1][0]+v[i-1][1],
        f[i-2][j-wi-wi-1][1]+v[i-2][i])
#include<bits/stdc++.h>
using namespace std;
#define int long long 

int n, k;
int const N = 5100;
int s[N], w[N];
int f[N][N][2];

void solve(){
    int cnt=0;
    cin>>n>>k;
    for(int i=0; i<=n; i++) s[i]=0;
    for(int i=1; i<=n; i++){
        int x, v;
        cin>>x>>v;
        if(x==1) s[cnt+1]+=v;
        else w[++cnt]=v;
    }
    if(cnt<2){
        cout<<"0\n";
        return ;
    }
    for(int i=1; i<=cnt; i++) s[i]+=s[i-1]; 
    for(int i=1; i<=cnt; i++) for(int j=0; j<=k; j++) f[i][j][0]=f[i][j][1]=LONG_LONG_MIN/2;
    f[1][0][0]=0; f[1][0][1]=LONG_LONG_MIN/2;
    for(int j=1; j<=k; j++) f[1][j][1]=LONG_LONG_MIN/2, f[1][j][0]=0;
    for(int j=0; j<=k; j++) f[2][j][1]=LONG_LONG_MIN/2, f[2][j][0]=0;
    f[2][0][0]=0; f[2][w[1]+w[2]][1]=s[2]-s[1];
    for(int i=3; i<=cnt; i++){
        for(int j=0; j<=k; j++){
            f[i][j][0]=max(f[i-1][j][0], f[i-1][j][1]);
            if(j>=w[i]+w[i-1]){
                f[i][j][1]=max(f[i-2][j-w[i]-w[i-1]][1]+s[i-1]-s[i-2], 
                    f[i-2][j-w[i]-w[i-1]][0])+s[i]-s[i-1];
            }
        }
    }
    int res=0;
    for(int i=0; i<=k; i++)
        res=max(res, max(f[cnt][i][0], f[cnt][i][1]));
    cout<<res<<'\n';
}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0), cout.tie(0);

    int T = 1;
    cin >> T;
    while(T --){
        solve();
    }    

    return 0;
} 
  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值