牛客练习赛132

题目:A 春

链接:A-春_牛客练习赛132

思路:只需要把最短的两条分别放在最两端即可。最短的两条只需要计算一次(所有的等腰梯形的上底和下底全部算上,这两条只需要加一次),其他的都需要加上两次。

代码:

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
int main()
{
	int n;
	cin>>n;
	vector<int> a(n);
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	sort(a.begin(),a.end());
	if(n>1){
		swap(a[1],a.back());//两个最小值放一前一后
	}
	ll ans=0;
	for(int i=0;i<n-1;i++){
		ans+=a[i]+a[i+1];
	}
	if(ans&1) cout<<ans/2<<".50";//奇数
	else cout<<ans/2<<".00";
	return 0;
}
	

题目:B 江

链接:B-江_牛客练习赛132

思路:排序去重后,使用双指针算法,尽可能使用上鬼牌,所有区间的最大值就是答案

代码:

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

int n, m, k;
int a[maxn];

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0), cout.tie(0);
    cin >> n >> m >> k;
    vector<int> v;
    for(int i = 1; i <= n; i++) {
        int x;
        cin >> x;
        v.push_back(x);
    }
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());// 去除vector v中的重复元素
    n = v.size();//更新元素个数
    int ans = 0;
    for(int l = 0, r = 0; l < v.size(); l++){
        while(r + 1 < v.size() &&// 尝试扩展右边界r,直到不能满足条件为止
		 v[r + 1] - v[l] + 1 - (r - l + 2) <= k) r++;
		 //(区间长度 - 不同元素数量) <= k
		 //[l, r+1]内最多可以有的重复元素数量
        ans = max(ans, k + r - l + 1);
    }
    cout << min(ans, m);
    return 0;
}

题目:C 水

链接:C-水_牛客练习赛132

思路:所有情况减去不是美丽图的情况(不能平分)即为答案

代码:

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

#define pb emplace_back
#define mp make_pair

using ll = long long;
using pii = pair<int,int>;

constexpr int mod = 1e9 + 7;
constexpr int inf = 0x3f3f3f3f;
constexpr int N = 1e7 + 10;

ll pow_mod(ll x, int p){
  ll s = 1;
  while(p){
    if(p & 1) s = s * x % mod;
    x = x * x % mod;
    p >>= 1;
  }
  return s;
}
ll fac[N];////阶乘数组
ll rev[N];//逆元数组
ll C(int n, int m){// 计算组合数 C(n, m) % mod
  if(n < m) return 0;
  return fac[n] * rev[m] % mod * rev[n-m] % mod;
}

void _main(){
  // 初始化阶乘数组
  fac[0] = 1;
  for(int i=1; i<N; ++i)  fac[i] = fac[i-1] * i % mod;

  // 初始化逆元数组
  rev[N-1] = pow_mod(fac[N-1], mod - 2);//计算最大阶乘的逆元
  for(int i=N-1; i>0; --i)  rev[i-1] = rev[i] * i % mod;

  int T, n, k;
  cin >> T;
  while(T--){
    cin >> n >> k;
    if(n & 1){
      cout << "0\n";
    } else {
      ll ans = C(n, k) - C(n / 2, k) * pow_mod(2, k) % mod;
      if(ans < 0) ans += mod;
      cout << ans << '\n';
    }
  }
}

int main(){
  ios::sync_with_stdio(0);
  cin.tie(0); cout.tie(0);
  _main();
  return 0;
}

 

posted @ 2024-12-02 20:39  hanbaodao  阅读(8)  评论(0编辑  收藏  举报