C
考虑先确定第一位,确定第一位以后每一位都可以通过前一位得到,考虑 哪些位上必须为 或必须为 ,没有限制的位就先填 ,然后就可以得到第 个序列的 ,那些没有限制的位填 的二进制位就可以得到第 个序列的 。
表示 的第 位必须为 , 表示 的第 位没有限制。
。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
void solve() {
int n, k;
cin >> n >> k;
k--;
vector<int> b(n - 1);
for (int i = 0; i < n - 1; i++) {
cin >> b[i];
}
int s = 0;
vector<int> c(30, -1);
for (int i = 0; i < n - 1; i++) {
int lg = __lg(b[i]);
s ^= b[i];
if (b[i]) {
if (c[lg] == (s >> lg & 1 ^ 1)) {
cout << "-1\n";
return;
}
c[lg] = s >> lg & 1;
}
}
int j = 0;
i64 a0 = 0;
for (int i = 0; i < 30; i++) {
if (c[i] == 0) {
a0 |= 1 << i;
} else if (c[i] == -1) {
a0 |= (k >> j++ & 1) << i;
}
}
for (int i = 30; j <= 30; i++) {
a0 |= (1LL * (k >> j++ & 1)) << i;
}
vector<i64> a{a0};
for (int i = 0; i < n - 1; i++) {
a.push_back(a0 ^= b[i]);
}
for (int i = 0; i < n; i++) {
if (a[i] >= (1 << 30)) {
cout << "-1\n";
return;
}
}
for (int i = 0; i < n; i++) {
cout << a[i] << " \n"[i == n - 1];
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
G
,无法进行任何操作, 全为 则 YES,否则 NO。
,重构成若干环形数组,问题变为每次选择两个相邻的数减一,问能否全变为 ,考虑解方程。
记环形数组为 ,长度为 ,设 和 减了 , 和 减了 ,, 和 减了 。
那么 。
若 为奇,利用 解出 ,然后解出所有 。
若 为偶,利用 ,求 的上界下界来判断。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
#define range(a) begin(a), end(a)
void solve() {
int n, k;
cin >> n >> k;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
if (k > n / 2) {
if (a == vector<int>(n)) {
cout << "YES\n";
} else {
cout << "NO\n";
}
return;
}
auto check = [&](const vector<int> &a) {
int m = a.size();
if (m % 2 == 1) {
i64 cur = 0;
for (int i = 0; i < m; i++) {
if (i % 2 == 0) {
cur += a[i];
} else {
cur -= a[i];
}
}
if (cur % 2 == 1) {
return false;
}
i64 x = cur / 2;
for (int i = 0; i < m; i++) {
x = a[i] - x;
if (x < 0) {
return false;
}
}
return true;
} else {
i64 cur = 0;
i64 mn = 0, mx = a[0];
for (int i = 1; i < m; i++) {
if (i % 2 == 1) {
cur += a[i];
mx = min(mx, cur);
} else {
cur -= a[i];
mn = max(mn, cur);
}
}
cur -= a[0];
mn = max(mn, cur);
if (cur != 0) {
return false;
}
return mn <= mx;
}
};
vector<int> vis(n);
for (int i = 0; i < n; i++) {
if (vis[i]) {
continue;
}
vector<int> cir;
for (int j = i; !vis[j]; j = (j + k) % n) {
vis[j] = 1;
cir.push_back(a[j]);
}
if (!check(cir)) {
cout << "NO\n";
return;
}
}
cout << "YES\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
I
,如果长度小于等于 那直接子集枚举,发现 ,考虑根号分治。
长度小于等于 枚举该长度的所有 串。
长度大于等于 证明数量一定小于等于 ,同样考虑子集枚举,合并,然后容斥。
复杂度不会算。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
constexpr int P = 998244353;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<vector<string>> a(401);
for (int i = 0; i < n; i++) {
string s;
cin >> s;
a[(int) s.size()].push_back(s);
}
i64 ans = 0;
for (int len = 1; len <= 400; len++) {
int m = a[len].size();
if (!m) {
continue;
}
if (len <= 20) {
for (int mask = 0; mask < (1 << len); mask++) {
for (auto &s : a[len]) {
bool ok = 1;
for (int i = 0; i < len; i++) {
if (s[i] != '?' && s[i] - '0' != (mask >> i & 1)) {
ok = 0;
break;
}
}
if (ok) {
ans = (ans + 1) % P;
break;
}
}
}
} else {
for (int mask = 1; mask < (1 << m); mask++) {
i64 cnt = 1;
for (int j = 0; j < len; j++) {
int c0 = 0, c1 = 0;
for (int i = 0; i < m; i++) {
if (mask >> i & 1) {
if (a[len][i][j] == '0') {
c0++;
}
if (a[len][i][j] == '1') {
c1++;
}
}
}
if (c0 && c1) {
cnt = 0;
break;
}
if (!c0 && !c1) {
cnt = (cnt * 2) % P;
}
}
if (__builtin_popcount(mask) & 1) {
ans = (ans + cnt) % P;
} else {
ans = (ans + P - cnt) % P;
}
}
}
}
cout << ans << '\n';
return 0;
}
L
每次 都跑一次 。
。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, b, p;
cin >> n >> m >> b >> p;
vector<int> s(n);
for (int i = 0; i < n; i++) {
cin >> s[i];
}
i64 ans = 0;
i64 res = 0;
i64 pw = 1;
for (int i = 0; i < m; i++) {
int o;
cin >> o;
if (o == 1) {
int x;
i64 c;
cin >> x >> c;
s[(x ^ res) % n] = c ^ res;
} else {
pw = pw * b % p;
int tn;
cin >> tn;
vector<int> t(tn);
for (int i = 0; i < tn; i++) {
i64 ti;
cin >> ti;
t[i] = ti ^ res;
}
if (tn < n) {
res = 0;
} else {
vector<int> nex(n + 1);
for (int i = 1, j = 0; i < n; i++) {
while (j && s[i] != s[j]) {
j = nex[j];
}
if (s[i] == s[j]) {
j++;
}
nex[i + 1] = j;
}
int cnt = 0;
for (int i = 0, j = 0; i < tn; i++) {
while (j && t[i] != s[j]) {
j = nex[j];
}
if (t[i] == s[j]) {
j++;
}
if (j == n) {
j = nex[j];
cnt++;
}
}
res = 1LL * nex[n] * cnt % p;
ans = (ans + res * pw % p) % p;
}
}
}
cout << ans << '\n';
return 0;
}
M
。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
void solve() {
int n;
cin >> n;
i64 ans = 0;
for (i64 p = 1; p <= n; p *= 10) {
ans += n - p + 1;
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}