Codeforces Round 957 (Div. 3) A~G

这场div3是我的第一次上绿,真的难呀,必须好好补补,前面五题都是偏思维模拟的
最后一题值得补,是一道快速幂+逆元求组合数的,这题挺好的学到了新东西

Codeforces Round 957 (Div. 3)

A. Only Pluses

链接:Problem - A - Codeforces

思路:

让这三个数相差最小,他们相乘的数最大

代码:

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

const int N = 2e5 + 10;
int a[N];

void solve() {
  int a , b , c;
  cin >> a >> b >> c;
  int k = 5;
  while(k--) {
    if(a <= b && a <= c) a++;
    else if(b <= a && b <= c) b++;
    else c++;
  }
  cout << a * b * c << endl;
}

signed main()
{
  ios::sync_with_stdio(false);
  int t;
  cin >> t;
  while(t--) solve();
  return 0;
}

B. Angry Monk

链接:Problem - B - Codeforces

思路:

将给定的数组排序,前 n − 1 n-1 n1个数,如果为 1 1 1结果直接加一,如果不为 1 1 1,结果加上 a [ i ] ∗ 2 − 1 a[i] * 2 - 1 a[i]21,最后输出即可

代码:

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

const int N = 2e5 + 10;
int a[N];

void solve() {
  int n , k;
  cin >> n >> k;
  for(int i = 1 ; i <= k ; i++) cin >> a[i];
  int ans = 0;
  sort(a + 1 , a + k + 1);
  for(int i = 1 ; i < k ; i++) {
    if(a[i] == 1) ans++;
    else ans += a[i] * 2 - 1;
  }
  cout << ans << endl;
}

signed main()
{
  ios::sync_with_stdio(false);
  int t;
  cin >> t;
  while(t--) solve();
  return 0;
}

C. Gorilla and Permutation

链接:Problem - C - Codeforces

思路:

要使结果 ∑ i = 1 n f ( i ) − ∑ i = 1 n g ( i ) \sum_{i=1}^{n}f(i)-\sum_{i=1}^{n}g(i) i=1nf(i)i=1ng(i)最大

  1. 把大于等于 k k k的数排在前面,并且按照从大到小的顺序排列
  2. 如果 m < k m<k m<k,接下来就排列大于 m m m小于 k k k的数,顺序没要求
  3. 最后排列 < = m <=m <=m的数,从小到大排列

这样求出来的值为最大

代码:

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

const int N = 2e5 + 10;
int a[N];

void solve() {
  int n , m , k;
  cin >> n >> m >> k;
  while(n) {
    if(n >= k) {
      cout << n << " ";
      n--;
    }
    else break;
  }
  for(int i = m + 1 ; i <= n ; i++) cout << i << " ";
  for(int i = 1 ; i <= m ; i++) cout << i << " ";
  cout << endl;
}

signed main()
{
  ios::sync_with_stdio(false);
  int t;
  cin >> t;
  while(t--) solve();
  return 0;
}

D. Test of Love

链接:Problem - D - Codeforces

思路:

根据题意遍历一下字符串

  1. s [ i ] = L s[i]=L s[i]=L:就在 i i i~ i + m i+m i+m找是否还存在 L L L,若存在直接跳到这上面,继续遍历,若不存在则跳到 i + m i+m i+m上面
  2. s [ i ] = W s[i]=W s[i]=W:只能往前游一格,如果前面为 C C C,则直接输出 " N O " "NO" "NO",当然也要计算游了多少格,如果游了超过 k k k,则也输出 " N O " "NO" "NO"
  3. s [ i ] = C s[i]=C s[i]=C:直接输出 " N O " "NO" "NO"
  4. 最后没问题直接输出 " Y E S " "YES" "YES"

代码:

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

const int N = 2e5 + 10;

void solve() {
  int n , m , k;
  cin >> n >> m >> k;
  string s;
  cin >> s;
  int ans = 0;
  int l = 0;
  s = 'L' + s;
  for(int i = 0 ; i <= n ;) {
    if(s[i] == 'L') {
      int l = i + m;
      i++;
      while(i <= n && i < l) {
        if(s[i] != 'L') i++;
        else break;
      }
      if(s[i] == 'C') {
        cout << "NO" << endl;
        return;
      }
    } else if(s[i] == 'W') {
      ans++;
      i++;
    } else {
      cout << "NO" << endl;
      return;
    }
  }
  if(ans <= k) cout << "YES" << endl;
  else cout << "NO" << endl;
}

signed main()
{
  ios::sync_with_stdio(false);
  int t;
  cin >> t;
  while(t--) solve();
  return 0;
}

E. Novice’s Mistake

链接:Problem - E - Codeforces

思路:

直接枚举 a a a b b b肯定会超时,通过 a ∗ n − b a*n-b anb发现结果最多六位,所以先枚举 a a a,然后枚举位数,去计算 b b b,看结果会不会相等

代码:

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

void solve() {
  int n;
  cin >> n;
  vector<pair<int , int>> v;//记录结果
  string s1 = to_string(n);
  for(int i = 1 ; i <= 10000 ; i++) {//枚举a,a的范围题目给的是1~10000
    string s2 = "";
    while(s2.size() <= 10) s2 += s1;//因为结果最多六位,保险取前面10位即可
    for(int j = 1 ; j <= 6 ; j++) {//枚举位数
      int b = s1.size() * i - j;//计算b
      if(b < 1 || b > min(10000ll , i * n)) continue;//看b是不是在范围内,题目也给了
      if(to_string(i * n - b) == s2.substr(0 , j)) v.push_back({i , b});//判断两次计算结果是否相同
    }
  }
  cout << v.size() << endl;
  for(auto i : v) cout << i.first << " " << i.second << endl;
}

signed main()
{
  ios::sync_with_stdio(false);
  int t;
  cin >> t;
  while(t--) solve();
  return 0;
}

F. Valuable Cards

链接:Problem - F - Codeforces

思路:

就是遍历一下数组,如果这个数是x的因子,那么就加入到 m a p map map中,如果 m a p map map中已经含有了这个因子的另一半,那么就直接在这边截断,数量加一,否则将 m a p map map中所有的数与之相乘,如果小于 x x x,那么将这个数也存进 m a p map map中继续判断

代码:

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

const int N = 2e5 + 10;
int a[N];

void solve() {
  int n , x;
  cin >> n >> x;
  for(int i = 1 ; i <= n ; i++) cin >> a[i];
  int ans = 1;//一开始为一段
  unordered_map<int , int> mp;//用来记录x的因子
  for(int i = 1 ; i <= n ; i++) {
    if(x % a[i] == 0) {//如果这个数是x的因子,那么就可以影响结果
      if(mp[x / a[i]] > 0) {//如果这个因子的另一半存在,则直接截断
        ans++;
        i--;
        mp.clear();
      } else {
        vector<int> res;//用来存储满足条件的式子
        for(auto p : mp) {
          if(p.second == 0) continue;
          if(p.first * a[i] > x) continue;
          res.push_back(p.first * a[i]);
        }
        mp[a[i]]++;
        for(auto p : res) mp[p]++;
        res.clear();
      }
    }
  }
  cout << ans << endl;
}

signed main()
{
  ios::sync_with_stdio(false);
  int t;
  cin >> t;
  while(t--) solve();
  return 0;
}

G. Ultra-Meow

链接:Problem - G - Codeforces

思路:

逆元+快速幂==> 组合数

遍历集合的长度 i i i M E X MEX MEX结果所处的位置 j j j,要想选到 j j j,则 j j j是第 i + 1 i+1 i+1个不在集合中的数。则在区间 [ 1 , j − 1 ] [1,j-1] [1,j1]中有 i i i个数不在集合之中,所以我们在左边选出 j − 1 − i j-1-i j1i个数放入集合中,即 C ( m i n ( j − 1 , n ) , j − 1 − i ) C(min(j-1,n),j-1-i) C(min(j1,n),j1i) 剩下的 i − ( j − 1 − i ) = 2 ∗ i − j + 1 i-(j-1-i)=2*i-j+1 i(j1i)=2ij+1个数需要在右边去选,即 C ( m a x ( n − j , 0 ) , 2 ∗ i − j + 1 ) C(max(n-j,0),2*i-j+1) Cmax(nj,0),2ij+1),将其相乘后乘上权值 j j j,在最开始预处理一下组合数后累加起来即可

代码:

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

const int N = 2e5 + 10;
const int mod = 1e9 + 7;
int inv[N] , fac[N];//inv为逆元,fac为阶层

//快速幂
int quickpow(int a , int b) {
  int res = 1;
  while(b) {
    if(b & 1) res = res * a % mod;
    a = a * a % mod;
    b >>= 1;
  }
  return res;
}

void init() {
  fac[0] = inv[0] = 1;
  //求阶层
  for(int i = 1 ; i <= N ; i++) fac[i] = fac[i - 1] * i % mod;
  //求逆元
  inv[N] = quickpow(fac[N] , mod - 2);//用费小马定理求出
  for(int i = N - 1 ; i >= 1 ; i--) inv[i] = inv[i + 1] * (i + 1) % mod;//用递归求出剩下的数的逆元
}

//求组合数
int C(int n , int m) {
  if(n < 0 || m < 0 || m > n) return 0;
  if(m == 0) return 1;
  return fac[n] * inv[m] % mod * inv[n - m] % mod;
}

void solve() {
  int n;
  cin >> n;
  int ans = 0;
  for(int i = 0 ; i <= n ; i++) {
    for(int j = 1 ; j <= n + n + 1 ; j++) {
      int res = 1;
      res = res * C(min(n , j - 1) , j - 1 - i) % mod;
      res = res * C(max(0ll , n - j) , 2 * i - j + 1) % mod;
      res = res * j % mod;
      ans = (ans + res) % mod;
    }
  }
  cout << ans << endl;
}

signed main()
{
  ios::sync_with_stdio(false);
  int t;
  cin >> t;
  init();
  while(t--) solve();
  return 0;
}
Codeforces Round 894 (Div. 3) 是一个Codeforces举办的比赛,是第894轮的Div. 3级别比赛。它包含了一系列题目,其中包括题目E. Kolya and Movie Theatre。 根据题目描述,E. Kolya and Movie Theatre问题要求我们给定两个字符串,通过三种操作来让字符串a等于字符串b。这三种操作分别为:交换a中相同位置的字符、交换a中对称位置的字符、交换b中对称位置的字符。我们需要先进行一次预处理,替换a中的字符,然后进行上述三种操作,最终得到a等于b的结果。我们需要计算预处理操作的次数。 根据引用的讨论,当且仅当b[i]==b[n-i-1]时,如果a[i]!=a[n-i-1],需要进行一次操作;否则不需要操作。所以我们可以遍历字符串b的前半部分,判断对应位置的字符是否与后半部分对称,并统计需要进行操作的次数。 以上就是Codeforces Round 894 (Div. 3)的简要说明和题目E. Kolya and Movie Theatre的要求。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [Codeforces Round #498 (Div. 3) (A+B+C+D+E+F)](https://blog.csdn.net/qq_46030630/article/details/108804114)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [Codeforces Round 894 (Div. 3)A~E题解](https://blog.csdn.net/gyeolhada/article/details/132491891)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值