A和B猜拳,A告诉了B自己会出啥,但是A是个老六,他不会按照他告诉你的手势出拳,而是选择自己所认为一定能战胜你的手势。
现在你已经看透了他的小心思。请问,在知道他告诉你他要出什么手势的情况下,你应该出什么手势才能取胜?
因为按照题目意思A会出你按照他之前说的手势赢的那个手势,所以只要你出他之前出的那个手势就行。
#include
using namespace std;
int main(){
string s; cin >> s;
cout << s << endl;
return 0;
}
现在有一个文本框,里面有一个1;
你可以进行:选中文本输入框中的部分或全部字符,将选中的字符复制到剪贴板,然后立即将复制的内容粘贴到文本输入框末尾。
问最少多少次操作达成恰好n个数字1?
简单贪心,在当前1的个数小于n的时候采取增长最快的操作,即复制全部加到里面(*2操作),最后一次操作加上 n - now 的 1就行
#include
using namespace std;
#define int long long
signed main(){
int _; cin >> _;
while(_--){
int n, t = 1, res = 0; cin >> n;
while(t < n){
res ++;
t = t * 2;
}
cout << res << endl;
}
return 0;
}
首先因为 a % b = m 可以推出==> a >= m;
因此我们可以先让t = n - m;
这时我们有 a % b < t
所以有解的情况一定是 t > m, 这个时候我们可以构造 a = m, b = t;
#include
using namespace std;
int n, m, a, b;
int main(){
int _; cin >> _;
while(_--){
x = -1;
cin >> n >> m;
if(n <= m) cout << -1 << endl;
else{
int t = n - m;
if(m == 0){
a = 0, b = n;
cout << a << " " << b << endl;
continue;
}
if(m < t){
a = m, b = t;
cout << a << " " << b << endl;
}else{
cout << -1 << endl;
}
}
}
return 0;
}
两种操作谁大就用谁
我们有 x + a <= x * a =====> x > 1 && a > 1;
因此我们从左向右遍历一遍进行操作就行,但是得注意我们当前记录的值是存在取余操作的,我们得判断是否进行过取余操作,即不能简单地认为x的值就是当前记录的值
#include
using namespace std;
#define int long long
const int N = 2e5 + 10, mod = 998244353;
signed main(){
int _; cin >> _;
while(_--){
int n, x = 0, f = 0; cin >> n;
for(int i = 1; i <= n; i++){
int a; cin >> a;
if(a < 2 || (x < 2 && !f)){
x += a;
}else{
x = x * a;
}
if(x >= mod) f = 1;
x %= mod;
}
x %= mod;
cout << x << endl;
}
return 0;
}
你有一个括号序列,你需要把该序列变成合法的
为了把这个括号序列变合法,每次可以进行下面的操作:
交换任意两个相邻括号。
如果无论怎么操作都无法使括号序列变合法,输出 −1;
否则请输出他需要做的最少的操作次数。
首先我们确定无解的情况,因为我们进行交换的次数可以是无限的,所以只要左右括号的数量相等就一定可以将序列恢复成合法的,无解情况就是数量不相等。
最少操作情况:
对于每个左括号,如果前面有未匹配的右括号,则我们去向前匹配右括号,因为如果向后去匹配最近的右括号,会造成该左括号与匹配的右括号之间的左括号向前移动,不是最优选择。所以左括号向前匹配未匹配的右括号是一种最优选择;
向前匹配我们优先匹配最前的那个右括号,因为我们如果匹配后面的右括号,则后面接下来的左括号依然需要走上这段路程,而且还需要加上前面匹配的左括号的距离,即要跨过中间当前匹配好的括号组距离,而如果每个左括号匹配最前面的右括号就可以使前面的右括号右移,减少前面右括号与后面左括号的距离,也可以避免需要跨过已经匹配好的括号组。
#include
using namespace std;
#define int long long
const int N = 200010;
char s[N];
signed main(){
int _; cin >> _;
while(_--){
int n, cnt = 0, res = 0; cin >> n;
for(int i = 1; i <= n; i++){
cin >> s[i];
if(s[i] == '(') cnt++;
else cnt--;
}
if(cnt){
puts("-1");
}else{
for(int i = 1, l = 0, r = 0; i <= n; i++){
if(s[i] == ')'){
if(l > 0){
l--;
}else{
r++;
}
}else{
if(r > 0){
res += r;
r--;
}else{
l++;
}
}
}
cout << res << endl;
}
}
return 0;
}
首先明确一点:我们找到当前列数下的操作最小值需要的复杂度是o(n),n为数组长度
显然我们首先想到的是暴力枚举列数,求得最小值,这种方法复杂为n方
进行优化----------------->
我们取最坏情况列数m = 1, n = 2e5时候,可以发现一种构造:
令 t = sqrt(n);
把列数扩展成t列,开销为 t - m;
再随便选一列,花费 n / t 的开销调换成目标值
因此我们的最大开销就是 2 * t - m < 2 * t;
我们枚举 max(m - 2 * t, 1) 到 min(m + 2 * t, n)之间的列数就行;
#include
using namespace std;
const int N = 200010;
int a[N], n, m, p;
int main(){
int _; cin >> _;
while(_--){
cin >> n >> m >> p;
for(int i = 1; i <= n; i++){
cin >> a[i];
}
int b = 2 * sqrt(n + 1) + 7, res = 1e9;
for(int i = max(m - b, 1); i <= min(m + b, n); i++){
for(int j = 1; j <= i; j++){
int t = 0;
for(int k = j; k <= n; k += i){
if(a[k] != p) t++;
}
res = min(res, abs(i - m) + t);
}
}
cout << res << endl;
}
return 0;
}