牛客小白月赛 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;
}