Contestant^. Rank 154. Rating +119 (+469 -350).

不知道有没有可能在有生之年打到 cf 第1000场(

A. How Much Does Daytona Cost?

题意

给定一个序列 \(a\),以及一个整数 \(k\),判断 \(k\) 是否是 \(a\) 的任意子串中出现次数最多的字符。

思路

只要子串长度是 \(1\),那么该字符就是出现次数最多的字符。

那么,问题就转化为判断 \(k\) 是否在 \(a\) 中出现了。

时间复杂度:\(O(n)\)

对应AC代码

#define chatgpt3_5 "bits/stdc++.h"
#define chatgpt4 "bits/extc++.h"

#include chatgpt3_5

using namespace std;

//#define FLOATING_OCEAN

#define int long long
#define pii pair<int, int>
#define pipi pair<pii, pii>
#define tpi tuple<int, int, int>
#define fs first
#define sc second
#define pb emplace_back
#define ep emplace
#define rall(x) x.rbegin(),x.rend()
#define all(x) x.begin(),x.end()

const int N = 2e5 + 10, M = 2e5 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9, PI = acos(-1);

void solve() {
    int n, k;
    cin >> n >> k;
    bool ok = false;
    for(int i=1;i<=n;i++){
        int x;
        cin >> x;
        if(x == k) ok = true;
    }
    cout << (ok ? "YES\n" : "NO\n");
}

signed main() {
# ifdef FLOATING_OCEAN
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
# endif
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
//    init();
    int t = 1;
    cin >> t;
    while (t--) solve();
}

签到

B. Aleksa and Stack

题意

给定一个正整数 \(n\),构造一个长为 \(n\) 的严格递增序列,满足 \(3 \cdot a_{i + 2}\) 不被 \(a_i + a_{i + 1}\) 整除。

思路1

我们可以构造递增的 \(3\) 的倍数,并加上一定值,来让条件不成立。

具体来说,我们可以构造下面的序列:

\(4, 7, 8, 13, 16, 17, \ldots\)

给出如下证明:

  1. \(a_{3k + 1} + a_{3k + 2} = (9k + 4) + (9k + 7) = 18k + 11\)\(a_{3k + 3} = 9k + 8\)\(3 \cdot a_{3k + 3} = 27k + 24\)\(lcm(18, 27) = 54\)\((18k + 11) \cdot \frac{lcm(18, 27)}{18} = 54k + 33, (27k + 24) \cdot \frac{lcm(18, 27)}{27} = 54k + 48\)\(33 \neq 48\),从而无法整除。

  2. \(a_{3k + 2} + a_{3k + 3} = (9k + 7) + (9k + 8) = 18k + 15, a_{3k + 4} = 9k + 13\)\(3 \cdot a_{3k + 4} = 27k + 36\)\(lcm(18, 27) = 54\)\((18k + 15) \cdot \frac{lcm(18, 27)}{18} = 54k + 45, (27k + 36) \cdot \frac{lcm(18, 27)}{27} = 54k + 72\)\(45 \neq 72\),从而无法整除。

  3. \(a_{3k + 3} + a_{3k + 4} = (9k + 8) + (9k + 13) = 18k + 21, a_{3k + 5} = 9k + 16\)\(3 \cdot a_{3k + 4} = 27k + 48\)\(lcm(18, 27) = 54\)\((18k + 21) \cdot \frac{lcm(18, 27)}{18} = 54k + 63, (27k + 48) \cdot \frac{lcm(18, 27)}{27} = 54k + 96\)\(63 \neq 96\),从而无法整除。

从而,可得构造合法。

思路2

我们可以按顺序输出所有奇数,即:

\(1, 3, 5, 7, 9, \ldots\)

可以发现,\(3a_{i + 2}\) 为奇数,\(a_i + a_{i + 1}\) 是偶数,从而一定不满足整除条件。

时间复杂度:\(O(n)\)

对应AC代码1

#define chatgpt3_5 "bits/stdc++.h"
#define chatgpt4 "bits/extc++.h"

#include chatgpt3_5

using namespace std;

//#define FLOATING_OCEAN

#define int long long
#define pii pair<int, int>
#define pipi pair<pii, pii>
#define tpi tuple<int, int, int>
#define fs first
#define sc second
#define pb emplace_back
#define ep emplace
#define rall(x) x.rbegin(),x.rend()
#define all(x) x.begin(),x.end()

const int N = 2e5 + 10, M = 2e5 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9, PI = acos(-1);

void solve() {
    int n;
    cin >> n;
    for(int i=1;i<=n;i++) {
        cout << i * 3 + 1 - (i % 3 == 0) << ' ';
    }
    cout << '\n';
}

signed main() {
# ifdef FLOATING_OCEAN
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
# endif
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
//    init();
    int t = 1;
    cin >> t;
    while (t--) solve();
}

对应AC代码2

#define chatgpt3_5 "bits/stdc++.h"
#define chatgpt4 "bits/extc++.h"

#include chatgpt3_5

using namespace std;

//#define FLOATING_OCEAN

#define int long long
#define pii pair<int, int>
#define pipi pair<pii, pii>
#define tpi tuple<int, int, int>
#define fs first
#define sc second
#define pb emplace_back
#define ep emplace
#define rall(x) x.rbegin(),x.rend()
#define all(x) x.begin(),x.end()

const int N = 2e5 + 10, M = 2e5 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9, PI = acos(-1);

void solve() {
    int n;
    cin >> n;
    for(int i=1;i<=n;i++) {
        cout << i * 2 - 1 << ' ';
    }
    cout << '\n';
}

signed main() {
# ifdef FLOATING_OCEAN
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
# endif
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
//    init();
    int t = 1;
    cin >> t;
    while (t--) solve();
}

难绷,也是写出了很神奇的构造(

C. Vasilije in Cacak

题意

给定三个正整数 \(n, k, x\),判断是否可以在 \([1, n]\) 中选择不同的 \(k\) 个数,使总和为 \(x\)

思路

通过观察,我们可以发现,总和在 \([\)\(k\) 小的数之和 \(,\)\(k\) 大的数之和 \(]\) 之间,且可以取任意值。

那么,我们只要计算一下区间的左右端点,然后判断 \(x\) 是否在区间内即可。

注意特殊情况的边界判断。

时间复杂度:\(O(n)\)

对应AC代码

#define chatgpt3_5 "bits/stdc++.h"
#define chatgpt4 "bits/extc++.h"

#include chatgpt3_5

using namespace std;

//#define FLOATING_OCEAN

#define int long long
#define pii pair<int, int>
#define pipi pair<pii, pii>
#define tpi tuple<int, int, int>
#define fs first
#define sc second
#define pb emplace_back
#define ep emplace
#define rall(x) x.rbegin(),x.rend()
#define all(x) x.begin(),x.end()

const int N = 2e5 + 10, M = 2e5 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9, PI = acos(-1);

void solve() {
    int n, k, x;
    cin >> n >> k >> x;
    if((k + 1) * k / 2 > x || (n + n - k + 1) * k / 2 < x) cout << "NO\n";
    else cout << "YES\n";
}

signed main() {
# ifdef FLOATING_OCEAN
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
# endif
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
//    init();
    int t = 1;
    cin >> t;
    while (t--) solve();
}

差点没想到这个结论(x

D. Reverse Madness

题意

给定一个字符串,并将字符串分割为 \(k\) 段,给定这 \(k\) 段的左右端点。

现在,给定 \(q\) 次修改,每次修改给定一个正整数 \(x\),将 \([\min(x, r + l - x), \max(x, r + l - x)]\) 内的字符串翻转。

输出最后一次修改后的字符串。

思路

首先,既然我们只要知道最后一次修改后的字符串,那么我们只需知道每一个位置被修改了几次即可。

考虑到区间修改,我们可以使用差分数组,最后判断每个位置的值的奇偶性即可。

至于判断当前位于哪个区间,我们可以二分。

时间复杂度:\(O(n + q)\)

对应AC代码

#define chatgpt3_5 "bits/stdc++.h"
#define chatgpt4 "bits/extc++.h"

#include chatgpt3_5

using namespace std;

//#define FLOATING_OCEAN

#define int long long
#define pii pair<int, int>
#define pipi pair<pii, pii>
#define tpi tuple<int, int, int>
#define fs first
#define sc second
#define pb emplace_back
#define ep emplace
#define rall(x) x.rbegin(),x.rend()
#define all(x) x.begin(),x.end()

const int N = 2e5 + 10, M = 2e5 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9, PI = acos(-1);

void solve() {
    int n, k;
    cin >> n >> k;
    string s;
    cin >> s;
    s = " " + s;
    vector<int> l(k + 1), r(k + 1);
    for(int i=1;i<=k;i++) cin >> l[i];
    for(int i=1;i<=k;i++) cin >> r[i];
    int q;
    cin >> q;
    vector<int> d(n + 2);
    while(q --){
        int x;
        cin >> x;
        int ind = lower_bound(all(r), x) - r.begin();
        int a = min(x, r[ind] + l[ind] - x), b = max(x, r[ind] + l[ind] - x);
        d[b + 1] ^= 1;
        d[a] ^= 1;
    }
    for(int i=1;i<=n;i++) d[i] ^= d[i - 1];
    for(int i=1;i<=k;i++){
        for(int j = l[i];j <= (l[i] + r[i]) / 2;j++){
            if(d[j]) swap(s[j],s[r[i] - (j - l[i])]);
        }
    }
    for(int i=1;i<=n;i++) cout << s[i];
    cout << '\n';
}

signed main() {
# ifdef FLOATING_OCEAN
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
# endif
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
//    init();
    int t = 1;
    cin >> t;
    while (t--) solve();
}

不然就用树状数组(x

E. Iva & Pav

题意

给定一个序列 \(a\),定义 \(f(l, r) = a_l~\&~a_{l + 1}~\& \ldots \&~a_r\)

给定 \(q\) 次询问,每次询问给定两个整数 \(k, l\),输出最大的 \(r\),使 \(f(l, r) \geq k\)

思路

显然,在左端点确定的情况下,右端点越大,\(f(l, r)\) 越小。

所以我们只需二分即可。

具体来说,我们预处理前缀与,然后二分处理每个询问。

时间复杂度:\(O(n \log n)\)

对应AC代码

#define chatgpt3_5 "bits/stdc++.h"
#define chatgpt4 "bits/extc++.h"

#include chatgpt3_5

using namespace std;

//#define FLOATING_OCEAN

#define int long long
#define pii pair<int, int>
#define pipi pair<pii, pii>
#define tpi tuple<int, int, int>
#define fs first
#define sc second
#define pb emplace_back
#define ep emplace
#define rall(x) x.rbegin(),x.rend()
#define all(x) x.begin(),x.end()

const int N = 2e5 + 10, M = 2e5 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9, PI = acos(-1);

void solve() {
    int n;
    cin >> n;
    vector<vector<int>> a(n + 1, vector<int>(32));
    vector<int> x(n + 1);
    for(int i=1;i<=n;i++){
        cin >> x[i];
        bitset<32> bs(x[i]);
        for(int j=0;j<=30;j++){
            a[i][j] = a[i - 1][j];
            if(bs[j]) a[i][j] ++;
        }
    }
    auto check = [&](int l, int k, int x){
        int cur = 0;
        for(int i=0;i<=30;i++){
            if(a[x][i] - a[l - 1][i] == x - l + 1) cur |= (1ll << i);
        }
        return cur >= k;
    };
    int q;
    cin >> q;
    while(q --){
        int l, k;
        cin >> l >> k;
        if(x[l] < k) {
            cout << -1 << ' ';
            continue;
        }
        int L = l, R = n, mid;
        while(L < R){
            mid = (L + R + 1) >> 1;
            if(check(l, k, mid)) L = mid;
            else R = mid - 1;
        }
        cout << L << ' ';
    }
}

signed main() {
# ifdef FLOATING_OCEAN
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
# endif
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
//    init();
    int t = 1;
    cin >> t;
    while (t--) solve();
}

位运算的常见结论(x

F. Vasilije Loves Number Theory

题意

给定一个整数 \(n\),定义询问如下:

  1. \(1~x\),将 \(n\) 乘上 \(x\),即 \(n := n \cdot x\),并判断是否存在整数 \(a\),使 \(\gcd(a, n) = 1, d(n \cdot a) = n\),其中 \(d(x)\)\(x\) 的因子个数;

  2. \(2\),将 \(n\) 赋值为一开始的给定值

现在,给定 \(q\) 次询问,执行对应的操作。

思路

首先,因为 \(\gcd(n, a) = 1\),所以 \(d(n \cdot a) = d(n) \times k\)

从而,条件转化为:\(n\)\(d(n)\) 的倍数。

由算术基本定理,若 \(n = p_1^{\alpha_1} \cdot p_2^{\alpha_2}\cdot \ldots \cdot p_k^{\alpha_k}\),那么 \(d(n) = (\alpha_1 + 1)(\alpha_2 + 1)\ldots(\alpha_k + 1)\)

直接算乘积是不可行的,那么我们考虑对质因数考虑:只要对于每个质因子,在 \(d(n)\) 的乘积中的出现次数 \(cnt_1\) 大于等于在 \(n\) 的乘积中出现的次数 \(cnt_2\),那么就满足条件。

因而,我们维护一下质因子个数的序列即可。

时间复杂度:\(O(太复杂了)\)

对应AC代码

#define chatgpt3_5 "bits/stdc++.h"
#define chatgpt4 "bits/extc++.h"

#include chatgpt3_5

using namespace std;

//#define FLOATING_OCEAN

#define int long long
#define pii pair<int, int>
#define pipi pair<pii, pii>
#define tpi tuple<int, int, int>
#define fs first
#define sc second
#define pb emplace_back
#define ep emplace
#define rall(x) x.rbegin(),x.rend()
#define all(x) x.begin(),x.end()

const int N = 2e5 + 10, M = 2e5 + 10, mod = 998244353, inf = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9, PI = acos(-1);

struct MATH {
private:
    struct PRIME {
        int Check_Num = 0, Max_Factor = 0;
        vector<pii> Dec;
    private:
        void Get_Fac(int Num) { //寻找 Num 的最大因子
            if (Num <= Max_Factor || Num < 2) return;
            if (Miller_Rabin(Num)) return void(Max_Factor = max(Max_Factor, Num));
            int Fac = Num;
            while (Fac >= Num) Fac = Pollard_Rho(Num);//寻 找 因 子
            while (!(Num % Fac)) Num /= Fac;
            return Get_Fac(Num), Get_Fac(Fac);
        }
        void Decomposition(int Num) { // 分解 Num 的质因子
            if (Num < 2) return;
            if (Miller_Rabin(Num)) {
                pair<int, int> Now = {Num, 0};
                while (Check_Num % Num == 0) Now.second++, Check_Num /= Num;
                if (Now.second) Dec.pb(Now);
                return;
            }
            int Fac = Num;
            while (Fac >= Num) Fac = Pollard_Rho(Num);//寻 找 因 子
            while (!(Num % Fac)) Num /= Fac;
            return Decomposition(Num), Decomposition(Fac);
        }
    public:
        __int128 test[16] = {0, 2, 3, 5, 7, 11, 13, 17, 19, 61, 325, 9375, 28178, 450775, 9780504, 1795265022};
        bool Miller_Rabin(__int128 P) { //检测 P 是不是质数, 严格保证答案正确
            if (P < 3 || P % 2 == 0) return P == 2;
            static int i, j;
            static __int128 Tem, k, Next;
            Tem = P - 1, k = 0;
            while (Tem % 2 == 0) Tem >>= 1, ++k;
            for (j = 1; j <= 15; j++) {
                Next = qp(test[j], Tem, P);
                if (Next <= 1 || Next == P - 1) continue;
                for (i = 0; i < k; ++i) {
                    Next = Next * Next % P;
                    if (Next == P - 1 && i != k - 1) {
                        Next = 1;
                        break;
                    }
                    if (Next == 1) return false;
                }
                if (Next != 1) return false;
            }
            return true;
        }
        static bool RMiller_Rabin(__int128 P, int test_time = 8) { //检测 P 是不是质数, 基于随机检验
            if (P < 3 || P % 2 == 0) return P == 2;
            static int i, j;
            static __int128 Tem, k, Rand_Num, Now;
            Tem = P - 1, k = 0;
            while (Tem % 2 == 0) Tem >>= 1, ++k;
            for (i = 1; i <= test_time; ++i) {
                Rand_Num = rand() % (P - 2) + 2, Now = qp(Rand_Num, Tem, P);
                if (Now == 1) continue;
                for (j = 0; j < k; ++j) {
                    if (Now == P - 1) break;
                    Now = Now * Now % P;
                }
                if (j >= k) return false;
            }
            return true;
        }
        static int Pollard_Rho(int x) {
            static int s, t, c, Div, Val;
            Val = 1, s = t = 0;
            static int Step, Goal;
            Step = 0, Goal = 1;
            c = (int) rand() % (x - 1) + 1;
            for (Goal = 1;; Goal <<= 1, s = t, Val = 1) { // 倍增优化
                for (Step = 1; Step <= Goal; ++Step) {
                    t = ((__int128) t * t + c) % x, Val = (__int128) Val * abs(t - s) % x;
                    if (!(Step % 127)) {
                        Div = __gcd(Val, x);
                        if (Div > 1) return Div;
                    }
                }
                Div = __gcd(Val, x);
                if (Div > 1) return Div;
            }
        }
        void Get_Max_Fac(int Num) { return Max_Factor = 0, Get_Fac(Num); } //获得 Num 的最大因子  测 试: Luogu P4718
        void Dec_Factor(int Num) { return Dec.clear(), Check_Num = Num, Decomposition(Num); } //分解 Num 的本质不同质因子  测 试: Prime Land
        int Get_Phi(int Num) { //计算 φ(Num)
            if (Num == 1) return 0;
            Dec_Factor(Num);
            for (auto &Now: Dec) Num = Num / Now.first * (Now.first - 1);
            return Num;
        }
    }pm;
public:
    static __int128 qp(__int128 x, __int128 y, __int128 m = mod) {
        static __int128 ans;
        ans = 1, x %= m;
        for (; y; y >>= 1, x = x * x % m) if (y & 1) ans = ans * x % m;
        return ans;
    }
    //ax+by=gcd(a,b),返回gcd
    int exgcd(int a, int b, int &x, int &y) {
        if (!b) {
            x = 1, y = 0;
            return a;
        }
        int d = exgcd(b, a % b, x, y);
        int t = x; x = y; y = t - (a / b) * y;
        return d;
    }
    //x (mod Mi) = Ai
    int exCRT(int n, int M[], int A[]) {
        int a = A[1], m = M[1], ta, tm, x, y, d, l, t;
        for (int i = 2; i <= n; i++) {
            tm = M[i], ta = A[i];
            d = exgcd(m, tm, x, y);
            l = m * tm / d;
            if ((ta - a) % d != 0) return -1;
            t = tm / d;
            x *= ((ta - a) / d);
            x = (x % t + t) % t;
            a += m * x;
            m = l;
        }
        return a;
    }
    //欧拉函数,小于等于n和n互质的数的个数
    int phi(int n) {
        return pm.Get_Phi(n);
    }
    bool vis[N];
    int pri[N], cnt;
    //线性筛
    void linear_prime(int n) {
        for (int i = 2; i <= n; ++i) {
            if (!vis[i]) pri[cnt++] = i;
            for (int j = 0; j < cnt; ++j) {
                if (1ll * i * pri[j] > n) break;
                vis[i * pri[j]] = true;
                if (i % pri[j] == 0)break;
            }
        }
    }
    int inv_ex(int n, int m = mod) {
        int x, y, ans = exgcd(n, m, x, y);
        if (ans == 1) return (x % m + m) % m;
        else return -1;
    }
    int inv(int n, int m = mod) { return qp(n, m - 2, m); }
    //p为1e5以内质数,求c(n, m) % p
    int lucas(int n, int m, int p) {
        if (m == 0) return 1;
        return (C(n % p, m % p, p) * lucas(n / p, m / p, p)) % p;
    }
    int C(int m, int n, int p) {
        int a = 1, b = 1;
        if (m < n) return 0;
        while (n) {
            a = (a * m) % p, b = (b * n) % p;
            m--, n--;
        }
        return a * inv_ex(b, p) % p;
    }
    void get_phi(int n, int phi[]) {
        for (int i = 0; i <= n; i++) phi[i] = i;
        for (int i = 2; i <= n; i++)
            if (phi[i] == i) for (int j = 2; j <= n; j++) phi[j] = phi[j] / i * (i - 1);
    }
    //线性求逆元
    void get_inv(int n, int inv[], int p = mod) {
        inv[1] = 1;
        for (int i = 2; i <= n; i++) inv[i] = inv[i] = (p - p / i * inv[p % i] % p) % p;
    }
    //线性求阶乘,逆元,阶乘逆元
    void get_fact_inv(int n, int fac[], int Inv[], int fac_inv[], int p = mod) {
        fac[0] = fac_inv[0] = Inv[0] = fac[1] = fac_inv[1] = Inv[1] = 1;
        for (int i = 2; i <= n; i++) {
            fac[i] = fac[i - 1] * i % p;
            Inv[i] = (p - p / i * Inv[p % i] % p) % p;
            fac_inv[i] = fac_inv[i - 1] * Inv[i] % p;
        }
    }
    vector<pii> factorize(int x) { return pm.Dec_Factor(x), pm.Dec; }
    int max_factor(int x){ return pm.Get_Max_Fac(x), pm.Max_Factor; }
    void miller_rabin(__int128 P){ pm.Miller_Rabin(P); }
    void random_miller_rabin(__int128 P, int test_time = 8){ pm.RMiller_Rabin(P, test_time); }
    int pollard_pho(int x) { pm.Pollard_Rho(x); }
    template<class T> T ex_sqrt(T x) { //返回精度更高的sqrt
        T sqrtX = sqrt(x) - 1;
        while (sqrtX + 1 <= x / (sqrtX + 1)) sqrtX++;
        return sqrtX;
    }
}math;

void solve() {
    int n, q;
    cin >> n >> q;
    map<int, int> cnt, cnt_n, cnt_d, last;
    vector<pii > fac = math.factorize(n);
    for (auto it: fac) cnt_n[it.fs] += it.sc;
    last = cnt_n;
    while (q--) {
        int op, x;
        cin >> op;
        if (op == 2) {
            cnt_n = last;
            continue;
        }
        cin >> x;
        fac = math.factorize(x);
        for (auto e: fac) cnt_n[e.fs] += e.sc;
        for (auto it: cnt_n) {
            fac = math.factorize(it.sc + 1);
            for (auto e: fac) cnt_d[e.fs] += e.sc;
        }
        bool st = true;
        for (auto e: cnt_d) {
            if (cnt_n[e.fs] < e.sc) st = false;
        }
        cnt_d.clear();
        cout << (st ? "YES" : "NO") << '\n';
    }
}

signed main() {
# ifdef FLOATING_OCEAN
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
# endif
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
//    init();
    int t = 1;
    cin >> t;
    while (t--) solve();
}

有意思的数论(