51nod 1964 陵陵曾玩的数论题 (笛卡尔树+dsu合并)

求解 所有子区间的最大lcmlcm %mod 的乘积
在这里插入图片描述

#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <cmath>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const int mod_1 = mod - 1;
const int MAXN = 100003;
const int Sqr = (int)sqrt(MAXN) + 1;
struct Io
{
    char A[MAXN * 4],*L,*R;
    int count;
    Io()
    {
        L = R = A;
        count = MAXN * 4;
    }
    void Io_fread()
    {
        L = A;
        R = A + fread(A, sizeof(char), count, stdin);
    }
    int read()
    {
        int  tmp = 0;
        if (L == R)
        {
            Io_fread();
            if (L == R)return 0;
        }
        while (*L<'0'||*L>'9')
        {
            L++;
            if (L == R)
            {
                Io_fread();
                if (L == R)return 0;
            }
        }
        while (*L >= '0'&&*L <= '9')
        {
            tmp = tmp * 10 + (*L - '0');
            L++;
            if (L == R)
            {
                Io_fread();
                if (L == R)return tmp;
            }
        }
        return tmp;
    }
}I;
int used[MAXN];
int buf[MAXN];
int G[MAXN];
int tmp[MAXN];
int tmp2[MAXN];
int nxt[MAXN];
int fst[MAXN];
int bnxt[MAXN];
int bfst[MAXN];
int queue[MAXN];
int stk[MAXN];
int *wnxt = tmp, *wfst = tmp2, *AL = tmp, *AR = tmp2, *C = used;
int ans = 1;

struct node
{
    int c[2];
    int L, R;
    node()
    {
        L = R = c[0] = c[1] = 0;
    }
};

struct Decare
{
    node A[MAXN];
    int root;
    int deep;
    Decare()
    {
        root = 0;
        deep = 1;
    }
    void _insert(int key, int inof)
    {
        if (inof == 0)
        {
            root = deep++;
            tmp[root] = key;
            return;
        }
        while (inof)
        {
            if (tmp[inof] >= key)
            {
                tmp[deep] = key;
                G[deep] = inof;
                A[deep].c[0] = A[inof].c[1];
                A[inof].c[1] = deep;
                G[A[deep].c[0]] = deep;
                deep++;
                return;
            }
            inof = G[inof];
        }
        tmp[deep] = key;
        A[deep].c[0] = root;
        G[root] = deep;
        root = deep++;
    }
    void insert(int key)
    {
        _insert(key, deep - 1);
    }
    void BFS(int root)
    {
        memset(tmp, 0, sizeof tmp);
        int l = 0, r = 1;
        stk[0] = root;
        while (l < r)
        {
            int v = stk[l++];
            if (A[v].c[0])    stk[r++] = A[v].c[0];
            if (A[v].c[1])    stk[r++] = A[v].c[1];
        }
        int n = r;
        while (r--)
        {
            int v = stk[r];
            tmp[v] ++;
            tmp[G[v]] += tmp[v];
        }
        tmp[0] = 0;
        l = 0;    r = 1;
        A[root].L = 1;
        A[root].R = n;
        A[0].L = 1;
        A[0].R = 0;
        while (l<r)
        {
            int v = stk[l++];
            A[A[v].c[0]].L = A[v].L;
            A[A[v].c[0]].R = A[A[v].c[0]].L + tmp[A[v].c[0]] - 1;
            A[A[v].c[1]].L = A[A[v].c[0]].R + 2;
            A[A[v].c[1]].R = A[A[v].c[1]].L + tmp[A[v].c[1]] - 1;
            if (A[v].c[0])   stk[r++] = A[v].c[0];
            if (A[v].c[1])   stk[r++] = A[v].c[1];
        }
        memset(tmp, 0, sizeof tmp);
        memset(G, 0, sizeof G);
        A[0].L = 1;
        A[0].R = 0;
    }
}D;

int Pow(int a, int b)
{
    int tmp = 1;
    while (b)
    {
        if (b & 1)
            tmp = (LL)tmp*a%mod;
        a = (LL)a*a%mod;
        b >>= 1;
    }
    return tmp;
}

int A[MAXN];

int find_nxt(int k, int B)
{
    int top = -1, d = k;
    while (bnxt[d] <= B)
    {
        stk[++top] = d;
        d = bnxt[d];
    }
    while (top>-1)
    {
        int x = stk[top--];
        if (bnxt[x] == nxt[x])wnxt[x] = A[x] * (bnxt[x] - x);
        wnxt[x] += wnxt[bnxt[x]];
        bnxt[x] = d;
    }
    return wnxt[k] + (B - d + 1)*A[d];
}

int find_fst(int k, int B)
{
    int top = -1, d = k;
    while (bfst[d] >= B)
    {
        stk[++top] = d;
        d = bfst[d];
    }
    while (top>-1)
    {
        int x = stk[top--];
        if (bfst[x] == fst[x]) wfst[x] = A[x] * (x - bfst[x]);
        wfst[x] += wfst[bfst[x]];
        bfst[x] = d;
    }
    return wfst[k] + (d - B + 1)*A[d];
}

void BFS_1(int root, int P)
{
    int l = 0, r = 1;
    queue[0] = root;
    while (l < r)
    {
        int v = queue[l++];
        if (D.A[v].c[0])queue[r++] = D.A[v].c[0];
        if (D.A[v].c[1])queue[r++] = D.A[v].c[1];
    }
    while (r--)
    {
        int v = queue[r];
        int *c = D.A[v].c;
        int L = D.A[v].L;
        int R = D.A[v].R;
        if (L == R)
        {
            G[P] = (G[P] + (LL)A[L] * buf[L] % (mod_1)) % mod_1;
            continue;
        }

        int mid = (c[0]) ? D.A[c[0]].R + 1 : D.A[c[1]].L - 1;

        if ((D.A[c[0]].R - D.A[c[0]].L + 1)<(D.A[c[1]].R - D.A[c[1]].L + 1))
        {
            for (int i = mid; i >= L; i = fst[i])
            {
                if (nxt[i] <= R)
                {
                    int bk = fst[i] < L ? L : fst[i] + 1;
                    G[P] += ((LL)(i - bk + 1)*(nxt[i] - mid) % (mod - 1))*((LL)A[i] * buf[mid] % (mod - 1)) % (mod - 1);
                    if (G[P] >= mod - 1)G[P] -= mod - 1;
                    G[P] += (LL)(i - bk + 1)*(buf[mid]) % (mod - 1)*find_nxt(nxt[i], R) % (mod - 1);
                    if (G[P] >= mod - 1)G[P] -= mod - 1;
                }
                else
                {
                    int bk = fst[i]<L ? L : fst[i] + 1;
                    G[P] += ((LL)(i - bk + 1)*(R - mid + 1) % (mod - 1))*((LL)A[i] * buf[mid] % (mod - 1)) % (mod - 1);
                    if (G[P] >= mod - 1)G[P] -= mod - 1;
                }
            }
        }
        else
        {
            for (int i = mid; i <= R; i = nxt[i])
            {
                if (fst[i] >= L)
                {
                    int bk = nxt[i]>R ? R : nxt[i] - 1;
                    G[P] += ((LL)(bk - i + 1)*(mid - fst[i]) % (mod - 1))*((LL)A[i] * buf[mid] % (mod - 1)) % (mod - 1);
                    if (G[P] >= mod - 1)G[P] -= mod - 1;;
                    G[P] += (LL)(bk - i + 1)*buf[mid] % (mod - 1)*find_fst(fst[i], L) % (mod - 1);
                    if (G[P] >= mod - 1)G[P] -= mod - 1;
                }
                else
                {
                    int bk = nxt[i]>R ? R : nxt[i] - 1;
                    G[P] += ((LL)(bk - i + 1)*(mid - L + 1) % (mod - 1))*((LL)A[i] * buf[mid] % (mod - 1)) % (mod - 1);
                    if (G[P] >= mod - 1)G[P] -= mod - 1;
                }
            }
        }
    }
}

void BFS_2(int root)
{
    int l = 0, r = 1;
    queue[0] = root;
    while (l < r)
    {
        int v = queue[l++];
        if (D.A[v].c[0])queue[r++] = D.A[v].c[0];
        if (D.A[v].c[1])queue[r++] = D.A[v].c[1];
    }

    while (r--)
    {
        root = queue[r];
        int *c = D.A[root].c;
        int L = D.A[root].L;
        int R = D.A[root].R;
        if (L == R)
        {
            G[A[buf[L]]] = (G[A[buf[L]]] + buf[L]) % mod_1;
            AL[root] = AR[root] = C[root] = A[buf[L]];
            continue;
        }
        int mid = (c[0]) ? D.A[c[0]].R + 1 : D.A[c[1]].L - 1;
        int tot = (LL)(mid - L + 1)*(R - mid + 1) % mod_1;
        if ((D.A[c[0]].R - D.A[c[0]].L) < (D.A[c[1]].R - D.A[c[1]].L))
        {
            AR[root] = (LL)AR[c[0]] * AR[c[1]] % mod;
            AL[root] = (LL)AL[c[0]] * AL[c[1]] % mod;
            C[root] = (LL)C[c[0]] * C[c[1]] % mod;
            for (int i = mid; i >= L; i--)
            {
                int &bk = nxt[i];
                if (bk <= mid)continue;
                int a = A[buf[i]];
                if (bk > R)
                {
                    G[a] += (LL)buf[mid] * (i - L + 1) % mod_1*(R - mid + 1) % mod_1;
                    if (G[a] >= mod_1)G[a] -= mod_1;
                    AR[root] = (LL)AR[root] * Pow(A[buf[i]], R - mid + 1) % mod;
                    int b = (i == mid) ? (fst[i]<L ? L : fst[i] + 1) : mid + 1;
                    AL[root] = (LL)AL[root] * Pow(A[buf[i]], mid - b + 1) % mod;
                    if ((i == mid && fst[i] >= L) || i != mid)
                        C[c[0]] = (LL)C[c[0]] * Pow(A[buf[i]], mod - 2) % mod;
                }
                else
                {
                    //bk<=R
                    int b = tot - (LL)(mid - i)*(bk - mid) % mod_1;
                    if (b < 0)b += mod_1;
                    G[a] += (LL)buf[mid] * b % mod_1;
                    if (G[a] >= mod_1)G[a] -= mod_1;
                    AR[c[1]] = (LL)AR[c[1]] * Pow(A[buf[i]], (LL)(mod - 2)*(R - bk + 1) % mod_1) % mod;
                    C[c[1]] = (LL)C[c[1]] * Pow(A[buf[i]], mod - 2) % mod;
                    if (i != mid)
                    {
                        C[c[0]] = (LL)C[c[0]] * Pow(A[buf[i]], mod - 2) % mod;
                        C[root] = (LL)C[root] * Pow(A[buf[i]], mod - 2) % mod;
                        AL[root] = (LL)AL[root] * Pow(A[buf[i]], mid - i) % mod;
                    }
                    else
                    {
                        C[c[0]] = (LL)C[c[0]] * (fst[i]<L ? 1 : Pow(A[buf[i]], mod - 2)) % mod;
                        C[root] = (LL)C[root] * (fst[i]<L ? 1 : Pow(A[buf[i]], mod - 2)) % mod;
                        AL[root] = (LL)AL[root] * Pow(A[buf[i]], mid + 1 - ((fst[i]<L) ? L : fst[i] + 1)) % mod;
                    }
                    AR[root] = (LL)AR[root] * Pow(A[buf[i]], bk - mid) % mod;//
                }
            }
            ans = (LL)ans*Pow(AR[c[1]], (LL)(mid - L + 1)*buf[mid] % (mod - 1)) % mod;
            AL[root] = (LL)AL[root] * Pow(C[c[1]], mid - L + 1) % mod;
            if (nxt[mid]>R&&fst[mid]<L) C[root] = (LL)C[root] * A[buf[mid]] % mod;
        }
        else
        {
            AR[root] = (LL)AR[c[0]] * AR[c[1]] % mod;
            AL[root] = (LL)AL[c[0]] * AL[c[1]] % mod;
            C[root] = (LL)C[c[0]] * C[c[1]] % mod;
            for (int j = mid; j <= R; j++)
            {
                int &bk = fst[j];
                int a = A[buf[j]];
                if (bk >= mid)continue;
                if (bk < L)
                {
                    G[a] += (LL)buf[mid] * (mid - L + 1) % (mod - 1)*(R - j + 1) % (mod - 1);
                    if (G[a] >= mod - 1)G[a] -= mod - 1;
                    AL[root] = (LL)AL[root] * Pow(A[buf[j]], mid - L + 1) % mod;
                    int b = (j == mid) ? (nxt[j] <= R ? nxt[j] - 1 : R) : mid - 1;
                    AR[root] = (LL)AR[root] * Pow(A[buf[j]], b - mid + 1) % mod;
                    if ((j == mid&&nxt[j] <= R) || j != mid)
                        C[c[1]] = (LL)C[c[1]] * Pow(A[buf[j]], mod - 2) % mod;
                }
                else
                {
                    int b = tot - (LL)(mid - bk)*(j - mid) % mod_1;
                    if (b < 0)b += mod_1;
                    G[a] += (LL)buf[mid] * b % mod_1;
                    if (G[a] >= mod - 1)G[a] -= mod_1;
                    AL[c[0]] = (LL)AL[c[0]] * Pow(A[buf[j]], (LL)(bk - L + 1)*(mod - 2) % mod_1) % mod;
                    C[c[0]] = (LL)C[c[0]] * Pow(A[buf[j]], mod - 2) % mod;
                    if (j != mid)
                    {
                        C[c[1]] = (LL)C[c[1]] * Pow(A[buf[j]], mod - 2) % mod;
                        C[root] = (LL)C[root] * Pow(A[buf[j]], mod - 2) % mod;
                        AR[root] = (LL)AR[root] * Pow(A[buf[j]], j - mid) % mod;
                    }
                    else
                    {
                        C[c[1]] = (LL)C[c[1]] * ((nxt[j] <= R) ? Pow(A[buf[j]], mod - 2) : 1) % mod;
                        C[root] = (LL)C[root] * ((nxt[j] <= R) ? Pow(A[buf[j]], mod - 2) : 1) % mod;
                        AR[root] = (LL)AR[root] * Pow(A[buf[mid]], ((nxt[j]>R) ? R : nxt[j] - 1) - mid + 1) % mod;
                    }
                    AL[root] = (LL)AL[root] * Pow(A[buf[j]], mid - bk) % mod;
                }
            }
            ans = (LL)ans*Pow(AL[c[0]], (LL)(R - mid + 1)*buf[mid] % mod_1) % mod;
            AR[root] = (LL)AR[root] * Pow(C[c[0]], R - mid + 1) % mod;
            if (nxt[mid]>R&&fst[mid]<L) C[root] = (LL)C[root] * A[buf[mid]] % mod;
        }
    }

}

void init(int n)
{
    A[0] = A[n + 1] = 0x3f3f3f3f;
    for (int i = 2; i < Sqr; i++)
    {
        if (used[i])continue;
        for (int j = i; j < MAXN; j += i)    used[j] = 1;

        for (int j = 1; j <= n; j++)
        {
            A[j] = 0;
            int t = buf[j];
            while (t%i == 0)
            {
                A[j]++;
                t /= i;
            }
        }

        memset(tmp, 0, sizeof tmp);
        memset(tmp2, 0, sizeof tmp2);
        stk[0] = 0;

        for (int j = 1, top = 0; j <= n; j++)
        {
            while (A[stk[top]] < A[j])top--;
            bfst[j] = fst[j] = stk[top];
            stk[++top] = j;
        }
        stk[0] = n + 1;

        for (int j = n, top = 0; j; j--)
        {
            while (A[stk[top]] <= A[j])top--;
            bnxt[j] = nxt[j] = stk[top];
            stk[++top] = j;
        }
        BFS_1(D.root, i);
    }
    for (int i = 0; i < MAXN; i++)A[i] = 1;
    for (int i = Sqr; i < MAXN; i++)
    {
        if (used[i])continue;
        for (int j = i; j < MAXN; j += i)
        {
            used[j] = 1;
            A[j] = i;
        }
    }
    memset(tmp, 0, sizeof tmp);
    for (int i = 1; i <= n; i++)
    {
        fst[i] = tmp[A[buf[i]]];
        tmp[A[buf[i]]] = i;
    }
    for (int i = 0; i < MAXN; i++)tmp[i] = n + 1;
    for (int j = n; j; j--)
    {
        nxt[j] = tmp[A[buf[j]]];
        tmp[A[buf[j]]] = j;
    }
    memset(tmp, 0, sizeof tmp);
    memset(tmp2, 0, sizeof tmp2);
    memset(used, 0, sizeof used);
    AL[0] = AR[0] = C[0] = 1;
    BFS_2(D.root);
}

int main()
{
    int n;
    n = I.read();
    for (int i = 1; i <= n; i++)
    {
        buf[i] = I.read();
        D.insert(buf[i]);
    }
    D.BFS(D.root);
    init(n);
    for (int i = 2; i < MAXN; i++) ans = (LL)ans*Pow(i, G[i]) % mod;
    printf("%d\n", ans);
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值