给你x,y,n,问你最大的k(1 <= k <= n)满足k mod x = y是多少
k = x * m + y <= n
m <= (n - y) / x
那么max(k) = [(n - y) / x] * x + y
#include
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--) {
ll x, y, n;
cin >> x >> y >> n;
cout <<(n - y) / x * x + y << '\n';
}
return 0;
}
给你一个n,每次你可以将他乘以2或者除以6(如果n % 6 == 0),问你n到达1的最少次数是多少,如果无法到达,输出-1
n * 6 -x * 2y = 1
n = 3x * 2x-y
num = x + y = 2 * x - (x - y)
所以将n分解为x个3相乘和x - y个2相乘即可
无法分解或者出现x > x - y表示num = -1
#include
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int t;
cin >> t;
while (t--) {
int n;
cin >> n;
int x = 0, xy = 0;
while (n % 3 == 0) {
++x;
n /= 3;
}
while (n % 2 == 0) {
++xy;
n /= 2;
}
int num = n == 1 && x >= xy ? 2 * x - xy : -1;
cout << num << '\n';
}
return 0;
}
给你一个由’(‘和’)'组成的字符串,每次你可以把一个字符移动到字符串头部或尾部,问你多少次后字符串合法,保证答案存在
用栈对括号进行匹配,剩下的无法匹配的字符中’('的个数即为答案
#include
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T;
cin >> T;
while (T--) {
int n;
cin >> n;
string s;
cin >> s;
stack<char> que;
for (int i = 0; i < n; ++i) {
if (que.empty() || s[i] == '(') {
que.push(s[i]);
}
else if (s[i] == ')') {
if (!que.empty() && que.top() == '(') que.pop();
else que.push(s[i]);
}
}
int a = 0, b = 0;
while (!que.empty()) {
if (que.top() == '(') ++a;
else ++b;
que.pop();
}
cout << min(a, b) << '\n';
}
return 0;
}
给你一个长度为n的数组a和数k,每次你可以选择一下两个操作中的一个,x初值为0:
问你多少次后数组中的数都可以被k整除
考虑由于x是在不停增加的,如果k - a[i] % k == k - a[j] % k,那么要想使得a[i]和a[j]同时达成条件,x需要在a[i]变成k的倍数后继续增加k然后加到a[j]上使得a[j]也变成k的倍数,那么答案已经呼之欲出了,我们将所有的a[i]变成k - a[i] % k(如果a[i] % k == 0就将其忽略),找到其中出现最多的那个数,假设为Max,出现次数为cnt(Max),那么我们需要将所有的Max变的满足条件,就需要(cnt(Max) - 1) * k + Max + 1次(加一是因为x初值为0),在这期间其余的所有数均有对应的x使其变成k的倍数(可以自己证明或者模拟一下),所以答案即为(cnt(Max) - 1) * k + Max + 1
#include
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
int a[maxn];
map<int, int> mp;
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
register int T;
cin >> T;
while (T--) {
register ll n, k;
cin >> n >> k;
register ll Max = 0;
mp.clear();
for (register int i = 1; i <= n; ++i) {
cin >> a[i];
if (a[i] % k == 0) {
a[i] = 0;
continue;
}
a[i] = a[i] / k * k + k - a[i];
++mp[a[i]];
if (mp[Max] < mp[a[i]]) Max = a[i];
else if (mp[Max] == mp[a[i]] && a[i] > Max) Max = a[i];
}
if (mp.empty()) {
cout << "0\n";
continue;
}
register ll res = Max + (mp[Max] - 1) * k + 1;
cout << res << '\n';
}
return 0;
}
Bob和Alice有n本书要阅读,每本书的阅读时间为t[i],其中有的书只有Bob喜欢,有的书只有Alice喜欢,有的书他们都喜欢,你要从里面挑一些书让他们共同阅读,并保证其中至少有k本Alice喜欢,有k本Bob喜欢,问你最小的阅读时间是多少
将书分成三类
a[i]记录Bob喜欢的书的阅读时间
b[i]记录Alice喜欢的书的阅读时间
c[i]记录他们都喜欢的书的阅读时间
假设现在从a中挑x本,从b中挑y本,从c中挑z本
那么其需要满足的条件为:
x + z >= k
y + z >= k
显然在等号处取得最优解
所以x = y
即解集中Bob和Alice单独喜欢的书的数量相同
那么我们将三个数组按时间大小排序,枚举x即可
#include
using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
int a[maxn], b[maxn], c[maxn], d[maxn];
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int n, k;
cin >> n >> k;
int cnta = 0, cntb = 0, cntc = 0;
for (int i = 1; i <= n; ++i) {
int t, x, y;
cin >> t >> x >> y;
if (x && y) {
c[++cntc] = t;
}
else if (x) a[++cnta] = t;
else if (y) b[++cntb] = t;
}
if (cnta + cntc < k || cntb + cntc < k) {
cout << "-1\n";
return 0;
}
sort(a + 1, a + cnta + 1);
sort(b + 1, b + cntb + 1);
sort(c + 1, c + cntc + 1);
for (int i = 1; i <= cntc; ++i) d[i] = d[i - 1] + c[i];
int res = 0, Min = 0x7fffffff;
int len = min(k, min(cnta, cntb));
for (int i = 1; i <= len; ++i) {
res += a[i] + b[i];
if (!d[k - i] && i != k) continue;
Min = min(Min, res + d[k - i]);
}
if (d[k]) Min = min(Min, d[k]);
cout << Min << '\n';
return 0;
}