A
- 排序即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--){
int n, k;
cin >> n >> k;
vector<pair<int, int> > a(n);
for(auto &i : a) cin >> i.first;
for(auto &i : a) cin >> i.second;
sort(a.begin(), a.end());
for(auto i : a){
if(k >= i.first) k += i.second;
}
cout << k << '\n';
}
return 0;
}
B
给你一个从 l l l到 r r r的连续序列,可以对这个序列进行 k k k次操作,每次操作可以选择两个数求乘积,得到结果放回原序列中,问能不能在 k k k次操作以内让这个序列任意两项的 g c d > 1 gcd>1 gcd>1
- 因为数字连续,所以我们选择 2 2 2作为质因子,那么答案就是总的数字个数 − - −含有因子 2 2 2的数字个数,也就是 r − l + 1 − ( r 2 − l − 1 2 ) r-l+1-(\frac r 2-\frac{l-1}2) r−l+1−(2r−2l−1)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--){
int l, r, k;
cin >> l >> r >> k;
if(l == r){
if(l == 1) cout << "NO\n";
else cout << "YES\n";
}else{
if(k >= r - l + 1 - (r / 2 - (l - 1) / 2)) cout << "YES\n";
else cout << "NO\n";
}
}
return 0;
}
C
给你一个数列,每次从中取出若干个数,求他们的 m e x mex mex并放入到 b b b数组中,并把原来的数删去,让你求出一个字典序最大的 b b b数组
- 尽可能的让第一个数更大,找尽可能大的 m e x mex mex,用一个指针记录当前位置,消耗一个较大的数是没有影响的
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--){
int n;
cin >> n;
vector<int> a(n), cnt(n + 1);
for(int i=0;i<n;i++){
cin >> a[i];
cnt[a[i]] += 1;
}
vector<bool> f(n + 1);
queue<int> q;
int p = 0;
while(p < n){
int now = 0;
while(cnt[now] > 0){
now += 1;
}
int num = 0;
while(num < now){
cnt[a[p]] -= 1;
if(!f[a[p]] && a[p] < now){
num += 1;
f[a[p]] = true;
}
p += 1;
}
if(now == 0) p += 1;
for(int i=0;i<now;i++){
f[i] = false;
}
q.push(now);
}
cout << q.size() << '\n';
while(!q.empty()){
cout << q.front() << ' ';
q.pop();
}
cout << '\n';
}
return 0;
}
D
让你从 n n n个字符串里面找到若干字符串按照顺序拼接起来组成一个回文串,字符串长度都在3以内,问能不能拼出来
- 显然如果字符串长度是1,那么它自己就是回文;如果字符串长度是2,那么可能和2或3两种情况构成回文;如果长度为3,那么可能和2和3两种情况构成回文,分别讨论即可
#include <bits/stdc++.h>
using namespace std;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--){
int n;
cin >> n;
bool ok = false;
set<string> two, three;
for(int i=0;i<n;i++){
string s;
cin >> s;
if(s.length() == 1) ok = true;
else if(s.length() == 2){
if(s[0] == s[1]) ok = true;
else{
string ss = s;
reverse(ss.begin(), ss.end());
if(two.count(ss)) ok = true;
for(char i='a';i<='z';i++){
if(three.count(ss + i)) ok = true;
}
two.insert(s);
}
}else{
if(s[0] == s[2]) ok = true;
else{
string ss = s;
reverse(ss.begin(), ss.end());
ss.pop_back();
if(two.count(ss)) ok = true;
ss = s;
reverse(ss.begin(), ss.end());
if(three.count(ss)) ok = true;
three.insert(s);
}
}
}
cout << (ok ? "YES" : "NO") << '\n';
}
return 0;
}
E
给你一个 n × n n\times n n×n的矩阵 b b b, b i , j b_{i,j} bi,j是由矩阵 a i , j a_{i,j} ai,j的上下左右四个数取异或和得到的,现在求 a a a矩阵的所有元素的异或和
- 有一种很简单的方法,任意给定矩阵 a a a的第一行,然后根据矩阵 b b b,求出整个矩阵 a a a,然后计算即可
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while(t--){
int n;
cin >> n;
vector<vector<int> > a(n, vector<int>(n));
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
cin >> a[i][j];
}
}
vector<vector<int> > res(n, vector<int>(n));
int ans = 0;
for(int i=1;i<n;i++){
for(int j=0;j<n;j++){
res[i][j] = a[i - 1][j];
if(j >= 1) res[i][j] ^= res[i - 1][j - 1];
if(j < n - 1) res[i][j] ^= res[i - 1][j + 1];
if(i >= 2) res[i][j] ^= res[i - 2][j];
ans ^= res[i][j];
}
}
cout << ans << '\n';
}
return 0;
}
F1
a l i c e alice alice和 b o b bob bob玩游戏,一共有 n n n个回合,起始成绩为 0 0 0,每次 a l i c e alice alice选择一个 [ 0 , k ] [0,k] [0,k]内的实数, b o b bob bob可以选择加上或者减去,他至少要加 m m m次,问最终的成绩期望
- 设 d p [ i ] [ j ] dp[i][j] dp[i][j]为前 i i i个回合选择 j j j次加法得到的成绩,那么显然有 d p [ i ] [ j ] = d p [ i − 1 ] [ j − 1 ] + k + d p [ i − 1 ] [ j ] − k = d p [ i − 1 ] [ j − 1 ] + d p [ i − 1 ] [ j ] dp[i][j]=dp[i-1][j-1]+k+dp[i-1][j]-k=dp[i-1][j-1]+dp[i-1][j] dp[i][j]=dp[i−1][j−1]+k+dp[i−1][j]−k=dp[i−1][j−1]+dp[i−1][j]
- 初始状态为 d p [ i ] [ i ] = i × k dp[i][i]=i\times k dp[i][i]=i×k
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 1e9 + 7;
ll fastpow(ll base, ll power){
ll ans = 1;
while(power > 0){
if(power & 1) ans = ans * base % MOD;
base = base * base % MOD;
power >>= 1;
}
return ans;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
ll inv = fastpow(2, MOD - 2);
while(t--){
int n, m, k;
cin >> n >> m >> k;
vector<vector<ll> > dp(n + 1, vector<ll> (m + 1));
for(int i=1;i<=m;i++){
dp[i][i] = 1ll * i * k % MOD;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(i == j) continue;
dp[i][j] = (dp[i - 1][j - 1] + dp[i - 1][j]) % MOD * inv % MOD;
}
}
cout << dp[n][m] << '\n';
}
return 0;
}
F2
- 考虑从 d p [ i ] [ j ] dp[i][j] dp[i][j]到 d p [ n ] [ m ] dp[n][m] dp[n][m]的转移,相当于从 ( i , j ) (i,j) (i,j)到 ( n , m ) (n,m) (n,m)的路径数量,考虑每一行,我们已知的初始状态是 d p [ i ] [ i ] dp[i][i] dp[i][i],考虑从这个状态开始转移,但是 d p [ i ] [ i ] dp[i][i] dp[i][i]不能直接走到 d p [ i + 1 ] [ i + 1 ] dp[i+1][i+1] dp[i+1][i+1],所以控制第一步先让他到 d p [ i + 1 ] [ i ] dp[i+1][i] dp[i+1][i],然后就变成从 ( i + 1 , i ) (i+1,i) (i+1,i)到 ( n , m ) (n,m) (n,m)的路径数量,应该是 C n − i − 1 m − i C_{n-i-1}^{m-i} Cn−i−1m−i,因为每一次都会除以2,所以最终统计出答案还要除以 2 n − i 2^{n-i} 2n−i
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 1e9 + 7;
ll fastpow(ll base, ll power){
ll ans = 1;
while(power > 0){
if(power & 1) ans = ans * base % MOD;
base = base * base % MOD;
power >>= 1;
}
return ans;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
vector<ll> fac(1e6 + 5);
fac[0] = 1ll;
for(ll i=1;i<=1e6;i++){
fac[i] = fac[i - 1] * i % MOD;
}
function<ll(ll, ll)> C = [&](ll n, ll m){
if(n < m) return 0ll;
return fac[n] * fastpow(fac[n - m], MOD - 2) % MOD * fastpow(fac[m], MOD - 2) % MOD;
};
int t;
cin >> t;
while(t--){
ll n, m, k;
cin >> n >> m >> k;
ll ans = 0;
if(n == m){
cout << n * k % MOD << '\n';
continue;
}
for(int i=1;i<=m;i++){
ans += C(n - i - 1, m - i) * i % MOD * k % MOD * fastpow(fastpow(2ll, n - i), MOD - 2) % MOD;
ans %= MOD;
}
cout << ans << '\n';
}
return 0;
}