zoukankan      html  css  js  c++  java
  • NOI模拟题5 Problem A: 开场题

    Solution

    注意到(gcd)具有结合律:

    [gcd(a, b, c) = gcd(a, gcd(b, c)) ]

    因此我们从后往前, 对于每个位置(L), 找到每一段不同的(gcd(a_x, a_{x + 1}, cdots, a_R)). 我们注意到这样的(R)最多只有(log)段.

    每个位置合并其后面一个位置的信息.

    同时我们还维护序列的前缀异或和, 对于每个异或值, 都开一颗线段树来存储其出现的位置. 随便乱搞即可.

    #include <cstdio>
    #include <cctype>
    #include <vector>
    #include <algorithm>
    #include <map>
     
    typedef long long LL;
    using namespace std;
    namespace Zeonfai
    {
        inline LL getLL()
        {
            LL a = 0, sgn = 1; char c;
            while (! isdigit(c = getchar())) if (c == '-') sgn *= -1;
            while (isdigit(c)) a = a * 10 + c - '0', c = getchar();
            return a * sgn;
        }
    }
    const int N = (int)1e5, INF = (int)2e9;
    int n;
    LL a[N + 1], sum[N + 1];
    struct record
    {
        int ed; LL val;
        inline record(int _ed, LL _val) { ed = _ed; val = _val; }
    };
    vector<record> bck[N + 1];
    map<LL, int> mp;
    struct segmentTree
    {
        struct node
        {
            node *suc[2];
            inline node() { for (int i = 0; i < 2; ++ i) suc[i] = NULL; }
        }*rt;
        inline segmentTree() { rt = NULL; }
        node *insert(node *u, int L, int R, int pos)
        {
            if (u == NULL) u = new node;
            if (L == R) return u;
            if (pos <= L + R >> 1) u->suc[0] = insert(u->suc[0], L, L + R >> 1, pos);
            else u->suc[1] = insert(u->suc[1], (L + R >> 1) + 1, R, pos);
            return u;
        }
        inline void insert(int pos) { rt = insert(rt, 1, n, pos); }
        int find(node *u, int curL, int curR, int L, int R)
        {
            if (u == NULL) return INF;
            if (curL == curR) return curL;
            int res = INF, mid = curL + curR >> 1;
            if (L <= mid) res = min(res, find(u->suc[0], curL, mid, L, R));
            if (res == INF && R > mid) res = min(res, find(u->suc[1], mid + 1, curR, L, R));
            return res;
        }
        inline int find(int L, int R) { return find(rt, 1, n, L, R); }
    }seg[N];
    /* inline LL __gcd(LL a, LL b)
    {
        if (a < b) swap(a, b);
        while (b)
        {
            LL tmp = b;
            b = a % b;
            a = tmp;
        }
        return a;
    } */
    inline vector<record>::iterator getPrevious(vector<record>::iterator p) { return -- p; }
    int main()
    {
     
    #ifndef ONLINE_JUDGE
     
        freopen("start.in", "r", stdin);
        freopen("start.out", "w", stdout);
     
    #endif
     
        using namespace Zeonfai;
        n = getLL();
        for (int i = 1; i <= n; ++ i) a[i] = getLL();
        for (int i = n; i; -- i)
        {
            bck[i].push_back(record(i, a[i])); int tot = 1;
            if (i != n)
            {
                for (vector<record>::iterator p = bck[i + 1].begin(); p != bck[i + 1].end(); ++ p)
                    if (__gcd(p->val, a[i]) != bck[i][tot - 1].val)
                        bck[i].push_back(record(p->ed, __gcd(a[i], p->val))), ++ tot;
                    else bck[i][tot - 1].ed = p->ed;
            }
        }
        sum[0] = 0; mp.clear(); int tot = 0;
        for (int i = 1; i <= n; ++ i)
        {
            sum[i] = sum[i - 1] ^ a[i];
            if (mp.find(sum[i]) == mp.end()) mp[sum[i]] = tot ++;
            seg[mp[sum[i]]].insert(i);
        }
        LL K = getLL();
        for (int i = 1; i <= n; ++ i)
        {
            for (vector<record>::iterator p = bck[i].begin(); p != bck[i].end(); ++ p)
            {
                if (K % p->val) continue;
                int res = INF;
                if (mp.find(K / p->val ^ sum[i - 1]) != mp.end())
                    res = seg[mp[K / p->val ^ sum[i - 1]]].find(p == bck[i].begin() ? i : getPrevious(p)->ed + 1, p->ed);
                if (res != INF)
                {
                    printf("%d %d
    ", i, res);
                    return 0;
                }
            }
        }
        puts("no solution");
    }
    
  • 相关阅读:
    PTA —— 基础编程题目集 —— 函数题 —— 61 简单输出整数 (10 分)
    PTA —— 基础编程题目集 —— 函数题 —— 61 简单输出整数 (10 分)
    练习2.13 不用库函数,写一个高效计算ln N的C函数
    练习2.13 不用库函数,写一个高效计算ln N的C函数
    练习2.13 不用库函数,写一个高效计算ln N的C函数
    迷宫问题 POJ 3984
    UVA 820 Internet Bandwidth (因特网带宽)(最大流)
    UVA 1001 Say Cheese(奶酪里的老鼠)(flod)
    UVA 11105 Semiprime Hnumbers(H半素数)
    UVA 557 Burger(汉堡)(dp+概率)
  • 原文地址:https://www.cnblogs.com/ZeonfaiHo/p/7598537.html
Copyright © 2011-2022 走看看