#include <bits/stdc++.h>
using namespace std;
int main() {
int a, b;
vector<int> parent({0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7});
cin >> a >> b;
// 条件演算子を使って出力 (もちろん if で書いてもいい)
cout << (a == parent[b] ? "Yes" : "No");
// cout << (a == b / 2 ? "Yes" : "No"); // こっちでも OK (parent がいらなくなる)
return 0;
}
#include <bits/stdc++.h>
using namespace std;
int main() {
int n;
string s;
cin >> n >> s;
for (int i = 1; i < n; ++i) {
int k;
for (k = 0; k + i < n; ++k) {
if (s[k] == s[k + i]) break;
}
cout << k << '\n';
}
return 0;
}
A
を とした、 桁の 進数として考えることができる。#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
ll ans = 0;
string s;
cin >> s;
// S を |S| 桁の 26 進数としたときの値を求める
for (int i = 0, sz = s.size(); i < sz; ++i) {
ans *= 26;
ans += s[i] - 'A';
}
// |S| - 1 桁までの ID の個数を求める
ll num = 1, sum = 0;
for (int i = 1, sz = s.size(); i < sz; ++i) {
num *= 26;
sum += num;
}
ans += sum + 1;
/* 式をうまいことやると、こっちでまとめて求められることがわかる。
for (int i = 0, sz = s.size(); i < sz; ++i) {
ans *= 26;
ans += s[i] - 'A' + 1;
} */
cout << ans;
return 0;
}
#include <bits/stdc++.h>
using namespace std;
// DAG (= 閉路がない有向グラフ) かどうか判断
// 出次数が 0 の頂点を削除していくアルゴリズム
bool isDAG(const vector<vector<int>> &g) {
int sz = g.size();
vector<vector<int>> reverseG(sz);
vector<int> out(sz);
vector<bool> deleted(sz);
stack<int> leaves;
for (int u = 0; u < sz; ++u) {
for (int v : g[u]) {
reverseG[v].push_back(u);
}
}
for (int i = 0; i < sz; ++i) {
out[i] = g[i].size();
if (!out[i]) leaves.push(i);
}
int v;
while (!leaves.empty()) {
v = leaves.top();
leaves.pop();
deleted[v] = true;
for (int a : reverseG[v]) {
--out[a];
if (!out[a]) leaves.push(a);
}
}
for (int i = 0; i < sz; ++i) {
if (!deleted[i]) return false;
}
return true;
}
int main() {
int n;
cin >> n;
vector<string> s(n), t(n);
map<string, int> mapS; // mapS[S_i] = i
for (int i = 0; i < n; ++i) {
cin >> s[i] >> t[i];
mapS[s[i]] = i;
}
vector<vector<int>> g(n);
for (int i = 0; i < n; ++i) {
auto itr = mapS.find(t[i]);
// T_i = S_j となる j があるなら
if (itr != mapS.end()) {
g[i].push_back(itr->second); // i -> j の辺を張る
}
}
// 閉路がないなら "Yes" あるなら "No"
cout << (isDAG(g) ? "Yes" : "No");
return 0;
}
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
int main() {
int n;
cin >> n;
vector<ll> a(n);
for (int i = 0; i < n; ++i) cin >> a[i];
vector<ll> sum(n);
for (int i = 1; i < n; ++i) {
// 解説にはないけど、これでも sum を求められる。
// 1-indexed なら sum[i] = sum[i - 1] + A_{ceil(i / 2)}
sum[i] = sum[i - 1] + a[(i - 1) / 2];
}
vector<ll> dp(n);
for (int i = 1; i < n; ++i) {
for (int j = 0; j < i; ++j) {
dp[i] = max(dp[i], dp[j] + sum[i - j - 1]);
}
}
ll ans = 0;
// 1-indexed なので、sum[n - i] -> sum[n - i - 1]
for (int i = 0; i < n; ++i) ans = max(ans, dp[i] + sum[n - i - 1]);
cout << ans;
return 0;
}
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template <typename T> // 0-indexed
class BIT {
int n;
vector<T> data;
public:
BIT(int _n) : n(_n), data(n + 1, 0) {}
void add(int a, T w) {
for (int i = ++a; i <= n; i += i & -i) data[i] += w;
}
T sum(int a) { // [0, a]
T ret = 0;
for (int i = ++a; i > 0; i -= i & -i) ret += data[i];
return ret;
}
T sum(int l, int r) { // [l, r)
T ret = 0;
for (int i = r; i > 0; i -= i & -i) ret += data[i];
for (int i = l; i > 0; i -= i & -i) ret -= data[i];
return ret;
}
};
template <typename S, S (*op)(S, S), S (*e)()>
class SegmentTree {
int n;
vector<S> d;
public:
SegmentTree(int n) : SegmentTree(vector<S>(n, e())){};
SegmentTree(const vector<S>& v) : n(v.size()), d(n << 1) {
for (int i = 0; i < n; ++i) {
d[n + i] = v[i];
}
for (int i = n - 1; i > 0; --i) {
d[i] = op(d[i << 1], d[i << 1 | 1]);
}
}
void set(int pos, S x) { // 1 点更新
pos += n;
d[pos] = x;
for (int i = pos >> 1; i; i >>= 1) {
d[i] = op(d[i << 1], d[i << 1 | 1]);
}
}
S get(int pos) { return d[pos + n]; }
S fold(int l, int r) { // 区間取得
S retl = e(), retr = e();
for (l += n, r += n; l < r; l >>= 1, r >>= 1) {
if (l & 1) retl = op(retl, d[l++]);
if (r & 1) retr = op(d[--r], retr);
}
return op(retl, retr);
}
};
using S = bool;
S op(S a, S b) { return a & b; }
S e() { return true; }
int main() {
int n, q;
string s;
cin >> n >> s >> q;
vector<BIT<int>> charSum(26, BIT<int>(n)); // 文字の種類ごとの累積和
SegmentTree<S, op, e> sorted(n - 1); // ソートされているか
// 初期化
for (int i = 0; i < n - 1; ++i) sorted.set(i, s[i] <= s[i + 1]);
for (int i = 0; i < n; ++i) charSum[s[i] - 'a'].add(i, 1);
for (int i = 0; i < q; ++i) {
int t;
cin >> t;
if (t == 1) {
int x;
char c;
cin >> x >> c;
--x;
// 累積和の更新
charSum[s[x] - 'a'].add(x, -1);
charSum[c - 'a'].add(x, 1);
s[x] = c;
// ソートされているかの更新
if (x > 0) sorted.set(x - 1, s[x - 1] <= s[x]);
if (x < n - 1) sorted.set(x, s[x] <= s[x + 1]);
} else if (t == 2) {
int l, r;
cin >> l >> r;
--l;
if (!sorted.fold(l, r - 1)) { // ソートされてないなら
cout << "No\n";
continue;
}
int first, last;
bool flag = true; // 2 つ目の条件を満たすか
for (first = 0; first < 26;) {
if (charSum[first++].sum(l, r)) break;
}
for (last = 25; last >= 0;) {
if (charSum[last--].sum(l, r)) break;
}
for (int i = first; i <= last; ++i) {
if (charSum[i].sum(l, r) != charSum[i].sum(0, n)) {
flag = false;
break;
}
}
cout << (flag ? "Yes" : "No") << '\n';
}
}
return 0;
}
1
には何も辺を張らない。)2
の数) + (?
の数) と一致するか判断すれば OK (ただし、数はオリジナルのみの数)。#include <bits/stdc++.h>
#include <atcoder/all>
using namespace std;
using namespace atcoder;
// 隣接するマスを返す
vector<pair<long long, long long>> move(long long x, long long y){
vector<pair<long long, long long>> ret;
ret.emplace_back(x-1,y);
ret.emplace_back(x+1,y);
ret.emplace_back(x,y-1);
ret.emplace_back(x,y+1);
return ret;
}
int main() {
int h, w;
cin >> h >> w;
vector<string> c(h);
for (int i = 0; i < h; ++i) cin >> c[i];
int cntnot1 = 0;
// [h * w, h * w * 2) はコピーの頂点
// s は h * w * 2、t は h * w * 2 + 1
mf_graph<int> g(h * w * 2 + 2);
for (int i = 0; i < h; ++i) {
for (int j = 0; j < w; ++j) {
if (c[i][j] != '1') { // 1 ではないなら
++cntnot1; // カウント
if ((i ^ j) & 1) { // i + j が奇数のマスなら
g.add_edge(h * w * 2, i * w + j, 1); // s からの辺を張る
g.add_edge((h + i) * w + j, h * w * 2 + 1, 1); // コピーは t への辺を張る
for (auto [x, y] : move(i, j)) {
if (!(0 <= x && x < h && 0 <= y && y < w)) continue;
if (c[x][y] != '1') { // 隣接マスが 1 ではないなら
g.add_edge(i * w + j, x * w + y, 1); // 隣接マスへの辺を張る
}
}
if (c[i][j] == '?') { // ? なら
g.add_edge(i * w + j, (h + i) * w + j, 1); // コピーの同じマスへの辺を張る
}
} else { // i + j が偶数のマスなら
g.add_edge(i * w + j, h * w * 2 + 1, 1); // t への辺を張る
g.add_edge(h * w * 2, (h + i) * w + j, 1); // コピーは s からの辺を張る
for (auto [x, y] : move(i, j)) {
if (!(0 <= x && x < h && 0 <= y && y < w)) continue;
if (c[x][y] != '1') { // 隣接マスが 1 ではないなら
g.add_edge((h + i) * w + j, (h + x) * w + y, 1); // コピーに隣接マスへの辺を張る
}
}
if (c[i][j] == '?') {
g.add_edge((h + i) * w + j, i * w + j, 1); // コピーの同じマスからの辺を張る
}
}
}
}
}
// 完全マッチングなら "Yes" 違うなら "No"
cout << (g.flow(h * w * 2, h * w * 2 + 1) == cntnot1 ? "Yes" : "No");
return 0;
}
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
// 階乗など
template <const int mod>
class Factorial {
int n;
vector<long long> fac;
vector<long long> inv;
long long pow(long long n, long long m) {
long long ans = 1;
while (m) {
if (m & 1) ans = ans * n % mod;
n = n * n % mod;
m >>= 1;
}
return ans;
}
public:
Factorial(int _n) : n(max(0, _n)), fac(n + 1), inv(n + 1) {
fac[0] = 1;
inv[0] = 1;
for (int i = 1; i <= n; ++i) {
fac[i] = fac[i - 1] * i % mod;
}
inv[n] = pow(fac[n], mod - 2);
for (int i = n; i > 1; --i) {
inv[i - 1] = inv[i] * i % mod;
}
}
long long getFac(int a) { return fac[a]; }
long long getInv(int a) { return inv[a]; }
long long P(int a, int b) {
if (a < b) return 0;
return fac[a] * inv[a - b] % mod;
}
long long C(int a, int b) {
if (a < b) return 0;
return fac[a] * inv[b] % mod * inv[a - b] % mod;
}
};
// f * (1 + x + x^2 + …)
void mul1(vector<ll> &f, const int mod) {
for (int i = 1, sz = f.size(); i < sz; ++i) (f[i] += f[i - 1]) %= mod;
}
// f / (1 + x + x^2 + …)
void div1(vector<ll> &f, const int mod) {
for (int i = f.size() - 1; i > 0; --i) (f[i] += mod - f[i - 1]) %= mod;
}
// f * (1 + x^2 + x^4 + …)
void mul2(vector<ll> &f, const int mod) {
for (int i = 2, sz = f.size(); i < sz; ++i) (f[i] += f[i - 2]) %= mod;
}
int main() {
int n, k;
const int mod = 1000000007;
ll ans = 0;
cin >> n >> k;
vector<int> e(k);
for (int i = 0; i < k; ++i) cin >> e[i];
Factorial<mod> F(n);
// f = (1 + x + x^2 + …) で初期化
vector<ll> f(10001, 1);
for (int i = 1; i < n; ++i) mul1(f, mod);
// f = (1 + x + x^2 + …)^{n - i} * (1 + x^2 + x^4 + …)^i
for (int i = 0; i <= n; ++i) {
ll squareI = 1; // 特定の i 個が平方数である数列の数
for (int j = 0; j < k; ++j) {
(squareI *= f[e[j]]) %= mod;
}
// 包除原理
(ans += (i & 1 ? mod - 1 : 1) * F.C(n, i) % mod * squareI) %= mod;
div1(f, mod);
mul2(f, mod);
}
cout << ans;
return 0;
}