码迷,mamicode.com
首页 > 其他好文 > 详细

[Codeforces 986E] Prince's Problem

时间:2018-10-04 09:39:24      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:可以转化   blank   mod   style   数组   val   dde   div   代码   

[题目链接]

          https://codeforces.com/contest/986/problem/E

[算法]

        X到Y的路径积 , 可以转化为X到根的路径积乘Y到根的路径积 , 除以LCA到根的路径积 , 再除以LCA父节点到根的路径积

        考虑如何计算根到X路径上每个点与Value的GCD之积

        不妨对于每个质数P开一个数组cnt[] , 表示根到当前节点P^i有多少个 , 我们可以在DFS的过程中维护这个数组

        将询问离线即可

        时间复杂度 : O(V + NlogN + QlogV^2)

[代码]

       

#include<bits/stdc++.h>
using namespace std;
#define MAXLOG 30
const int P = 1e9 + 7;
const int MAXN = 1e5 + 10;
const int MAXP = 1e6 + 10;
const int MAXV = 1e7 + 10;

struct edge
{
        int to , nxt; 
} e[MAXN << 1];
struct info
{
        int value , home;
        bool type;
} ;
int tot , n , t;
int a[MAXN],depth[MAXN],prime[MAXP],head[MAXN],ans[MAXN],f[MAXV];
int cnt[MAXP][MAXLOG],anc[MAXN][MAXLOG];
vector< info > q[MAXN];

template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); }
template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); }
template <typename T> inline void read(T &x)
{
    T f = 1; x = 0;
    char c = getchar();
    for (; !isdigit(c); c = getchar()) if (c == -) f = -f;
    for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - 0;
    x *= f;
}
inline void addedge(int u,int v)
{
        t++;
        e[t] = (edge){v,head[u]};
        head[u] = t;
}
inline int exp_mod(int a,int n)
{
        int res = 1 , b = a;
        while (n > 0)
        {
                if (n & 1) res = 1ll * res * b % P;
                b = 1ll * b * b % P;
                n >>= 1;
        }
        return res;
}
inline int inv(int x) { return exp_mod(x,P - 2); }
inline void dfs(int u,int fa)
{
        depth[u] = depth[fa] + 1;
        for (int i = 1; i < MAXLOG; i++)
        {
                if (depth[u] <= (1 << i)) break;
                anc[u][i] = anc[anc[u][i - 1]][i - 1];    
        }    
        for (int i = head[u]; i; i = e[i].nxt)
        {
                int v = e[i].to;
                if (v == fa) continue;
                anc[v][0] = u;
                depth[v] = depth[u] + 1;
                dfs(v,u);
        }
}
inline int lca(int u,int v)
{
      if (depth[u] > depth[v]) swap(u,v);
        for (int i = MAXLOG - 1; i >= 0; i--)        
        {
                if (depth[anc[v][i]] >= depth[u])
                        v = anc[v][i];
        }
        if (u == v) return u;
        for (int i = MAXLOG - 1; i >= 0; i--)
        {
                if (anc[u][i] != anc[v][i])
                        u = anc[u][i] , v = anc[v][i];
        }
        return anc[u][0];
}
inline void modify(int x,int delta)
{
        for (int i = 1; 1ll * prime[i] * prime[i] <= x; i++)
        {
                if (x % prime[i] == 0)
                {
                        int p = 0;
                        while (x % prime[i] == 0)
                        {
                                x /= prime[i];
                                p++;
                        }
                        cnt[i][p] += delta;
                }
        }
        if (x != 1)
        {
                int pos = lower_bound(prime + 1,prime + tot + 1,x) - prime;
                cnt[pos][1] += delta;
        }
}
inline int query(int x)
{
        int ret = 1;
        for (int i = 1; 1ll * prime[i] * prime[i] <= x; i++)
        {
                if (x % prime[i] == 0)
                {
                        int p = 0;
                        while (x % prime[i] == 0)
                        {
                                p++;
                                x /= prime[i];
                        }
                        int s = 0;
                        for (int j = 1; j <= p; j++) s += cnt[i][j] * j;
                        for (int j = p + 1; j < MAXLOG; j++) s += cnt[i][j] * p;
                        ret = 1ll * ret * exp_mod(prime[i],s) % P;
                }
         }
         if (x != 1)
         {
                int pos = lower_bound(prime + 1,prime + tot + 1,x) - prime;
                int s = 0;
                for (int i = 1; i < MAXLOG; i++) s += cnt[pos][i];
                ret = 1ll * ret * exp_mod(x,s) % P;                
        }
        return ret;
}

inline void solve(int u,int fa)
{
        modify(a[u],1);
        for (unsigned i = 0; i < q[u].size(); i++)
        {
                if (q[u][i].type)    ans[q[u][i].home] = 1ll * ans[q[u][i].home] * query(q[u][i].value) % P;
                else ans[q[u][i].home] = 1ll * ans[q[u][i].home] * inv(query(q[u][i].value)) % P; 
        }        
        for (int i = head[u]; i; i = e[i].nxt)
        {
                int v = e[i].to;
                if (v == fa) continue;
                solve(v,u);
        }
        modify(a[u],-1);
}

int main()
{
        
        read(n);
        for (int i = 2; i < MAXV; i++)
        {
                if (!f[i]) 
                {
                        f[i] = i;
                        prime[++tot] = i;
                }
                for (int j = 1; j <= tot; j++)
                {
                        int tmp = i * prime[j];
                        if (tmp >= MAXV) break;
                        f[tmp] = prime[j];
                        if (prime[j] == f[i]) break;
                }
        }
        for (int i = 1; i < n; i++)
        {
                int u , v;
                read(u); read(v);
                addedge(u,v);
                addedge(v,u);
        }
        dfs(1,0);
        for (int i = 1; i <= n; i++) read(a[i]);
        int Q;
        read(Q);
        for (int i = 1; i <= Q; i++)
        {
                int u , v , x;
                read(u); read(v); read(x);
                int Lca = lca(u,v);
                q[u].push_back((info){x,i,true});
                q[v].push_back((info){x,i,true});
                q[Lca].push_back((info){x,i,false}); 
                if (Lca != 1) q[anc[Lca][0]].push_back((info){x,i,false});
                ans[i] = 1;
        }
        solve(1,0);
        for (int i = 1; i <= Q; i++) printf("%d\n",ans[i]);
        
        return 0;
    
}

 

[Codeforces 986E] Prince's Problem

标签:可以转化   blank   mod   style   数组   val   dde   div   代码   

原文地址:https://www.cnblogs.com/evenbao/p/9739488.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!