• [jzoj 5930] [NOIP2018模拟10.26】山花 解题报告 (质因数分类)


    题目链接:

    http://172.16.0.132/senior/#contest/show/2538/2

    题目:

    小S决定从某一个节点$u$开始对其子树中与$u$距离小于$K$的节点代表的花树进行采摘。

    特别的,节点$u$代表的花树也会被采摘。依旧受限于精力,小S并不会亲自去采摘而是使用Extremely Strong的工具进行采摘。

    我们定义一个工具的能力为$c$,小S会采摘的山树集合为$T$。那么小S能采摘到的山花数量$f_T = prod _{i∈T} (a_i, c)$

    现在对于给定的树和阀值$K$,小S想要知道每一组询问的$f_T$

    题解:

    考虑按质因数分类计算每个点的贡献

    对于一个质因子,我们把询问$c$值和点权$a$值放在一起按照指数排序。

    先从前往后扫,显然对于一个询问当前贡献为之前的点权指数之和;再从后往前扫,对于一个询问当前的贡献是后面的点的个数乘上当前询问的指数。这就是经典的通过排序确定大小关系后计算贡献的栗子

    直接用树状数组在$dfs$序上维护即可

    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<iostream>
    #include<vector>
    using namespace std;
    typedef long long ll;
    
    const int N=1e5+15;
    const int mo=998244353;
    const int M=1e7+15;
    int n,Q,k,tot,tim,cnt,tp;
    int t[N],dfn[N],pri[N],fk[N],ed[N],vis[M],head[N],fa[N],st[N];
    ll ANS[N];
    struct EDGE{
        int to,nxt;
    }edge[N<<1];
    struct QUE{
        int x,c;
    }q[N];
    struct node{
        int k,ty,id;
    }ck[N<<1];
    bool operator < (node x,node y) {return x.k<y.k||(x.k==y.k&&x.ty<y.ty);}
    vector <node> pi[N];
    inline int read(){
        char ch=getchar();int s=0,f=1;
        while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
        while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
        return s*f;
    }
    void div(int x,int ty,int id)
    {
        for (int i=2;i*i<=x;i++)
        {
            if (x%i) continue;
            int s=0;
            while (x%i==0) x/=i,++s;
            if (!vis[i]) pri[++cnt]=i,vis[i]=cnt;
            pi[vis[i]].push_back((node){s,ty,id});
        }
        if (x>1)
        {
            if (!vis[x]) pri[++cnt]=x,vis[x]=cnt;
            pi[vis[x]].push_back((node){1,ty,id});
        }
    }
    void link(int u,int v){edge[++tot]=(EDGE){v,head[u]};head[u]=tot;}
    void dfs(int x,int pre)
    {
        dfn[x]=++tim;st[++tp]=x;
        if (tp>k) fk[x]=st[tp-k];
        for (int i=head[x];i;i=edge[i].nxt){
            int y=edge[i].to;
            if (y==pre) continue;
            dfs(y,x);
        }
        tp--;ed[x]=tim;
    }
    void modify(int x,int y)
    {
        if (!x) return;
        while (x<=n) 
        {
            t[x]+=y;
            x+=x&-x;
        }
    }
    int query(int x)
    {
        int re=0;
        while (x)
        {
            re+=t[x];
            x-=x&-x;
        }
        return re;
    }
    ll qpow(ll a,ll b)
    {
        ll re=1;
        for (;b;b>>=1,a=a*a%mo) if (b&1) re=re*a%mo;
        return re;
    }
    int main()
    {
        freopen("C.in","r",stdin);
        freopen("C.out","w",stdout);
        n=read();Q=read();k=read();
        for (int i=1,a;i<=n;i++) a=read(),div(a,1,i);
        for (int i=1,u,v;i<n;i++)
        {
            u=read();v=read();
            link(u,v);link(v,u);
        }
        dfs(1,0);
        for (int i=1;i<=Q;i++)
        {
            q[i].x=read();q[i].c=read();
            div(q[i].c,2,i);
            ANS[i]=1;
        }
        for (int j=1;j<=cnt;j++)
        {
            int pnt=pi[j].size();
            sort(pi[j].begin(),pi[j].end());
            memset(t,0,sizeof(t));
            for (int i=0;i<pnt;i++)
            {
                int id=pi[j][i].id;
                if (pi[j][i].ty==1)
                {
                    modify(dfn[fk[id]],-pi[j][i].k);
                    modify(dfn[id],pi[j][i].k);
                }
                else
                {
                    int p=query(ed[q[id].x])-query(dfn[q[id].x]-1);
                    (ANS[id]*=qpow(pri[j],p))%=mo;
                }
            }
            for (int i=0;i<pnt;i++) 
            {
                int id=pi[j][i].id;
                if (pi[j][i].ty==1) 
                {
                    modify(dfn[fk[id]],pi[j][i].k);
                    modify(dfn[id],-pi[j][i].k);
                }
            }
            for (int i=pnt-1;i>=0;i--)
            {
                int id=pi[j][i].id;
                if (pi[j][i].ty==1)
                {
                    modify(dfn[fk[id]],-1);
                    modify(dfn[id],1);
                }
                else
                {
                    int p=query(ed[q[id].x])-query(dfn[q[id].x]-1);
                    (ANS[id]*=qpow(pri[j],p*pi[j][i].k))%=mo;
                }
            } 
            for (int i=pnt-1;i>=0;i--)
            {
                int id=pi[j][i].id;
                if (pi[j][i].ty==1)
                {
                    modify(dfn[fk[id]],1);
                    modify(dfn[id],-1);
                }
            }
        } 
        for (int i=1;i<=Q;i++) printf("%lld
    ",ANS[i]);
        return 0;
    }
  • 相关阅读:
    Element ui 的使用
    Vue基本介绍
    静态界面传值javascript
    手机网页怎么禁止缩放、拖放、如何屏蔽到手机本身键盘
    jQuery学习之prop和attr的区别示例介绍
    jquery复选框 选中事件 及其判断是否被选中
    手机端html5触屏事件(touch事件)
    页面滚动到底部自动 Ajax 获取文章
    转Python RegEx正则
    转Python 日期
  • 原文地址:https://www.cnblogs.com/xxzh/p/9881386.html
Copyright © 2020-2023  润新知