for
ループで単純に掛け算するだけで OK。 なので int
でもオーバーフローしない。C++ には pow
関数があるので、それを使ってもいい (ただし、cout
を使う場合、指数表記にならないように注意すること)。pow
関数だとオーバーフローする可能性がある。powl
関数を使えば、 程度でもオーバーフローしない。#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b;
cin >> a >> b;
// 整数型に変換して指数表記を回避
cout << (int)pow(a, b);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main() {
int n, q;
cin >> n;
vector<int> a(n + 1);
for (int i = 1; i <= n; ++i) cin >> a[i];
cin >> q;
for (int i = 0, t, k, x; i < q; ++i) {
cin >> t;
if (t == 1) {
cin >> k >> x;
a[k] = x;
} else {
cin >> k;
cout << a[k] << '\n';
}
}
return 0;
}
0
以外は、必ず 回ボタンを押す必要がある。0
の場合は、0
が 回連続しているとき、少なくとも 回ボタンを押す必要がある。このまま実装してもいいし、連続する 0
のうち奇数個目のときのみ カウントするのでもいい。#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
string s;
int ans = 0;
cin >> s;
bool odd0 = false; // 連続する 0 が奇数番目か
for (int i = 0, sz = s.size(); i < sz; ++i) {
if (s[i] == '0') { // 0 なら
odd0 ^= true; // 偶奇を反転
if (odd0) ++ans; // 奇数番目なら 1 加算
} else { // 0 でないなら
odd0 = false; // 0 の偶奇をリセット
++ans; // 1 加算
}
}
cout << ans;
return 0;
}
)
が来たときに消せるボールをそれぞれ保持しておけばいい。
)
が来たときに消せるボールは、(
が来るたびに別々に保持する必要があるので、以下のように実装する (以下は入力例 の図)。(
が来るたび、新しく格納場所を追加し、文字が来るたび、 番新しい格納場所に格納する。また、)
が来るたび、 番新しい格納場所に格納されているボールを全体のボールから消し、 番新しい格納場所も消す。Yes
。No
。set
や配列を使えば OK。また、格納場所の保持には stack
などがいい。文字の種類数を とおくと、set
なら 、配列なら 。#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
string s;
cin >> s;
// 全体のボール
vector<bool> ball(26);
// 格納場所の保持用
stack<vector<bool>> st;
// 初期状態の格納場所の個数は 1 個
st.push(vector<bool>(26));
for (int i = 0, sz = s.size(); i < sz; ++i) {
if (s[i] == '(') { // '(' なら
st.push(vector<bool>(26)); // 格納場所を追加
} else if (s[i] == ')') { // ')' なら
vector<bool> &del = st.top(); // 最新の格納場所を取得
// ボールを消す
for (int j = 0; j < 26; ++j) {
if (del[j]) ball[j] = false;
}
st.pop(); // 最新の格納場所を消す
} else { // 文字なら
if (ball[s[i] - 'a']) { // すでに箱にボールが入っているなら
cout << "No"; // 答えは "No"
return 0; // 終了
} else { // 入ってないなら
// それぞれに追加
ball[s[i] - 'a'] = true;
st.top()[s[i] - 'a'] = true;
}
}
}
// 操作を最後まで出来れば答えは "Yes"
cout << "Yes";
return 0;
}
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
// a_{i, j} が孤立しているか調べる
// prev, cur, next はそれぞれ i - 1 行目、i 行目、i + 1 行目を反転しているか (しているなら 1、していないなら 0)
bool isIsolate(int i, int j, int prev, int cur, int next, int h, int w, vector<vector<vector<int>>> &a) {
int x[4] = {1, 0, -1, 0};
int y[4] = {0, 1, 0, -1};
int rev[3] = {prev, cur, next};
for (int k = 0; k < 4; ++k) {
int ii = i + x[k], jj = j + y[k];
if (0 <= ii && ii < h && 0 <= jj && jj < w) {
if (a[cur][i][j] == a[rev[1 + x[k]]][ii][jj]) {
return false;
}
}
}
return true;
}
int main() {
int h, w;
cin >> h >> w;
// a[0] は A、a[1] は反転した A
vector<vector<vector<int>>> a(2, vector<vector<int>>(h, vector<int>(w)));
for (int i = 0; i < h; ++i)
for (int j = 0; j < w; ++j)
cin >> a[0][i][j], a[1][i][j] = a[0][i][j] ^ 1;
// 任意の要素が孤立した要素でない状態にすることが不可能な場合
const int INF = 1 << 30;
// dp[i][cur][next] は、0 ~ i 行目が孤立しないときの反転の最小回数
// cur, next はそれぞれ i 行目、i + 1 行目を反転しているか (しているなら 1、していないなら 0)
vector<vector<vector<int>>> dp(h, vector<vector<int>>(2, vector<int>(2, INF)));
// i = 0 のときの初期化
for (int cur = 0; cur < 2; ++cur) {
for (int next = 0; next < 2; ++next) {
bool flag = true; // 孤立をなくせるか
for (int j = 0; j < w; ++j) {
if (isIsolate(0, j, 0, cur, next, h, w, a)) {
flag = false;
break;
}
}
if (flag) { // 孤立をなくせるなら
dp[0][cur][next] = cur + next; // 反転回数を cur + next で初期化
}
}
}
for (int i = 1; i < h; ++i) {
for (int prev = 0; prev < 2; ++prev) {
for (int cur = 0; cur < 2; ++cur) {
for (int next = 0; next < 2; ++next) {
bool flag = true;
for (int j = 0; j < w; ++j) {
if (isIsolate(i, j, prev, cur, next, h, w, a)) {
flag = false;
break;
}
}
if (flag) {
dp[i][cur][next] =
min(dp[i][cur][next], dp[i - 1][prev][cur] + next);
}
}
}
}
}
int ans = min(dp[h - 1][0][0], dp[h - 1][1][0]);
cout << (ans == INF ? -1 : ans);
return 0;
}
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
// Manhattan MST
// 組 (最小全域木の辺のコストの総和, 辺) を返す
template <typename T>
pair<T, vector<tuple<T, int, int>>> RMST(vector<T> &xs, vector<T> &ys) {
int n = xs.size();
vector<int> idx(n);
iota(idx.begin(), idx.end(), 0);
vector<tuple<T, int, int>> edge;
auto comp = [&](int i, int j) { return xs[i] + ys[i] < xs[j] + ys[j]; };
/* --[begin]-- http://users.eecs.northwestern.edu/~haizhou/publications/zhou02ipl.pdf */
for (int s = 0; s < 2; ++s) {
sort(idx.begin(), idx.end(), comp);
for (int t = 0; t < 2; ++t) {
map<T, int> sweep;
for (int i : idx) {
for (auto itr = sweep.lower_bound(~xs[i]); itr != sweep.end(); itr = sweep.erase(itr)) {
int j = itr->second;
if (xs[j] - ys[j] < xs[i] - ys[i]) break;
edge.emplace_back(abs(xs[i] - xs[j]) + abs(ys[i] - ys[j]), i, j);
}
sweep[~xs[i]] = i;
}
swap(xs, ys);
}
for (int i = 0; i < n; ++i) xs[i] = -xs[i];
}
/* ---[end]--- http://users.eecs.northwestern.edu/~haizhou/publications/zhou02ipl.pdf */
sort(edge.begin(), edge.end());
T sum = 0;
vector<tuple<T, int, int>> ret;
class UnionFind {
vector<int> p;
public:
UnionFind(int n) : p(n, -1) {}
void unite(int x, int y) { x = find(x); y = find(y); if (x == y) return; if (p[x] < p[y]) { p[x] += p[y]; p[y] = x; } else { p[y] += p[x]; p[x] = y; } return; }
int find(int x) { if (p[x] < 0) return x; while (p[p[x]] >= 0) { p[x] = p[p[x]]; x = p[x]; if (p[x] < 0) return x; } return p[x]; }
bool isSame(int x, int y) { return find(x) == find(y); }
} uni(n);
for (auto [cost, i, j] : edge) {
if (!uni.isSame(i, j)) {
uni.unite(i, j);
sum += cost;
ret.emplace_back(cost, i, j);
}
}
return {sum, ret};
}
int main() {
int n;
cin >> n;
const int INF = 1 << 30;
vector<int> idx(n), p(n), ans(n, INF);
for (int i = 0; i < n; ++i) cin >> p[i], idx[i] = i;
auto [cost, edge] = RMST(idx, p);
// 最小全域木の辺をすべて走査して、最小値を更新
for (auto [d, i, j] : edge) {
ans[i] = min(ans[i], d);
ans[j] = min(ans[j], d);
}
for (int i = 0; i < n; ++i) cout << ans[i] << ' ';
return 0;
}
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
// ビット単位の掃き出し法 (返り値は rank)
int GaussianElimination(vector<ll> &a) {
int sz = a.size();
int rank = 0;
vector<int> top;
for (int i = 59; i >= 0; --i) {
bool flag = false;
for (int j = rank; j < sz; ++j) {
if (a[j] & (1ll << i)) {
swap(a[j], a[rank]);
flag = true;
top.push_back(i);
break;
}
}
if (flag) {
for (int j = rank + 1; j < sz; ++j) {
if (a[j] & (1ll << i)) {
a[j] ^= a[rank];
}
}
++rank;
}
}
for (int i = rank - 1; i > 0; --i) {
for (int j = i - 1; j >= 0; --j) {
if (a[j] & (1ll << top[i])) {
a[j] ^= a[i];
}
}
}
return rank;
}
int main() {
int n;
ll l, r;
cin >> n >> l >> r;
vector<ll> a(n);
for (int i = 0; i < n; ++i) cin >> a[i];
int rank = GaussianElimination(a);
// a_0, …, a_{rank - 1} は降順なので反転する
reverse(&a[0], &a[rank]);
// a_rank 以降は 0 なので要らない
a.resize(rank);
for (ll i = l - 1; i < r; ++i) {
ll output = 0;
for (int j = 0; j < rank; ++j) {
if (i & (1ll << j)) { // 1 が立っているビットのとき
output ^= a[j]; // xor を取る
}
}
cout << output << ' ';
}
return 0;
}
int popcount = x;
for (int i = x >> 1; i; i >>= 1) {
popcount -= i;
}
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
// i の範囲が [0, n) での floor((a * i + b) / m) の総和を返す
long long floorSum(long long n, long long m, long long a, long long b) {
long long ans = 0;
if (a < 0) {
long long apos = a % m;
if (apos < 0) apos += m;
ans -= n * (n - 1) / 2 * ((apos - a) / m);
a = apos;
}
if (b < 0) {
long long bpos = b % m;
if (bpos < 0) bpos += m;
ans -= n * ((bpos - b) / m);
b = bpos;
}
while (true) {
if (a >= m) {
ans += n * (n - 1) / 2 * (a / m);
a %= m;
}
if (b >= m) {
ans += n * (b / m);
b %= m;
}
long long ymax = a * n + b;
if (ymax < m) break;
n = ymax / m;
b = ymax % m;
swap(m, a);
}
return ans;
}
int main() {
int t;
int N, M, R;
cin >> t;
for (int i = 0; i < t; ++i) {
cin >> N >> M >> R;
// 1 以上 N 以下の整数であって、M で割った余りが R になるものの個数
int n = (N - R) / M + 1;
ll ans = 0;
for (int k = 0; k < 30; ++k) {
ans += floorSum(n, 1 << (k + 1), M, R + (1 << k)) -
floorSum(n, 1 << (k + 1), M, R);
}
cout << ans << '\n';
}
return 0;
}