这场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 n−1个数,如果为 1 1 1结果直接加一,如果不为 1 1 1,结果加上 a [ i ] ∗ 2 − 1 a[i] * 2 - 1 a[i]∗2−1,最后输出即可
代码:
#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)最大
- 把大于等于 k k k的数排在前面,并且按照从大到小的顺序排列
- 如果 m < k m<k m<k,接下来就排列大于 m m m小于 k k k的数,顺序没要求
- 最后排列 < = 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
思路:
根据题意遍历一下字符串
- 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上面
- s [ i ] = W s[i]=W s[i]=W:只能往前游一格,如果前面为 C C C,则直接输出 " N O " "NO" "NO",当然也要计算游了多少格,如果游了超过 k k k,则也输出 " N O " "NO" "NO"
- s [ i ] = C s[i]=C s[i]=C:直接输出 " N O " "NO" "NO"
- 最后没问题直接输出 " 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 a∗n−b发现结果最多六位,所以先枚举 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,j−1]中有 i i i个数不在集合之中,所以我们在左边选出 j − 1 − i j-1-i j−1−i个数放入集合中,即 C ( m i n ( j − 1 , n ) , j − 1 − i ) C(min(j-1,n),j-1-i) C(min(j−1,n),j−1−i) 剩下的 i − ( j − 1 − i ) = 2 ∗ i − j + 1 i-(j-1-i)=2*i-j+1 i−(j−1−i)=2∗i−j+1个数需要在右边去选,即 C ( m a x ( n − j , 0 ) , 2 ∗ i − j + 1 ) C(max(n-j,0),2*i-j+1) C(max(n−j,0),2∗i−j+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;
}