
思维大挑战这一块。
题目链接:https://codeforces.com/contest/2241
A - Divide and Conquer
大致题意:给定和,通过执行任意次(包括零次)除以自己任意的约数(因数)的操作可以得到。判断这和是否满足这个条件。
思路:通过题意我们可以知道其实只有当是的因数的时候才满足条件。在这种情况下一定能和的另一个因数相乘得到。我们判断是的因数时就输出,否则就。
#include <bits/stdc++.h>
using namespace std;using ll = long long;using ull = unsigned long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;
void solved() { int x, y; cin >> x >> y; if(x % y == 0) cout << "YES" << endl; else cout << "NO" << endl;}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; cin >> _; while (_--) { solved(); } return 0;}B - Good times Good times
大致题意:给定一个好数(所有十进制位上的出现的不同数字最多包含两种不同的数字),我们要找出另外一个好数,使得也是好数。
思路:这里我想到的构造方法是根据的十进制位数来构造一个,这样的只有和,所以满足是好数的条件。举个例子对于我们生成,相乘结果为,满足题意。对于我们生成,相乘结果为,个位的乘以后就将最高位和个位之间的全填满了,保证不会出现,由此能构造出满足条件的好数。
#include <bits/stdc++.h>
using namespace std;using ll = long long;using ull = unsigned long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;
void solved() { string x; cin >> x; ll y = 1; for(int i = 0; i < (int)x.size();i++) y *= 10; cout << y + 1 << endl;}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; cin >> _; while (_--) { solved(); } return 0;}C - RemovevomeR
大致题意:对于一个只包含和的字符串,可以进行任意次下面的操作:选一个里长度至少为的回文子串,从这个回文子串里删掉一个字符,剩下的字符拼接成新的字符串,求任意次操作完之后的最短是多少。
思路:首先全和全的最终结果为。然后我们通过手动模拟这样的操作可以发现一个规律:如果子串存在一个(比如,或者)的结构,那么就可以通过一定的操作使得最终的的长度为。反之除了这两种情况之外都会剩下和两个字符各一个,结果为。所以特判这两个特殊情况为,其他都是即可。
这里的实现我可能写的比较复杂,原理就是和分别记录和的下标。然后有如果其中一个为空就说明是全或全的情况直接输出。否则就根据第一个元素是或来遍历对应或的下标数组的元素找下标。如果这个数组里所有的元素都是递增的就说明没有出现的结构,最终就输出。否则就直接输出。
#include <bits/stdc++.h>
using namespace std;using ll = long long;using ull = unsigned long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;
void solved() { int n; cin >> n; vector<int> pos0, pos1; string s; cin >> s; for(int i = 0; i < (int)s.size();i++){ if(s[i] == '0') pos0.push_back(i); else pos1.push_back(i); } if(!pos1.size() || !pos0.size()){ cout << 1 << endl; return; } char first = s[0]; vector<int> pos = (first == '0' ? pos0 : pos1); for(int i = 0;i < (int)pos.size() - 1;i++){ if(pos[i] + 1 == pos[i + 1]) continue; else{ cout << 1 << endl; return; } } cout << 2 << endl;}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; cin >> _; while (_--) { solved(); } return 0;}D - An Alternative Way
大致题意:给定连两个长度都为的数组和,你可以通过对进行任意次一下操作:选择两个索引和,满足,对到之间的索引,执行为计数则,如果为偶数则。 问最终能否使得变成。
思路:我们注意到这个操作实现了一个交替加减的操作。我们用一个记录每一个变成需要的变化值。比如和的就是。这个样例是可以通过操作一步变成的,故输出。
此外更重要的是,我们注意到这个数组形成的前缀和中的每一项总是大于等于的。的前缀和数组为,对于一个,它的含义其实是在以当前为左端点的区间需要操作多少次,所以的值必须大于等于,反之如果小于就无法通过这样操作最终变成。所以我们直接判断每一个的前缀和是否小于,如果小于就输出,否则就输出即可。
#include <bits/stdc++.h>
using namespace std;using ll = long long;using ull = unsigned long long;#define endl '\n'#define mod 998244353typedef pair<ll, ll> pll;typedef pair<int, int> pii;
void solved() { int n; cin >> n; vector<ll> a(n + 1), b(n + 1); for(int i = 1; i <= n;i++) cin >> a[i]; for(int i = 1; i <= n;i++) cin >> b[i];
ll pref = 0; for(int i = 1; i <= n;i++){ pref += b[i] - a[i]; if(pref < 0){ cout << "NO" << endl; return; } } cout << "YES" << endl;}
int main() { ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); int _ = 1; cin >> _; while (_--) { solved(); } return 0;}