zoukankan      html  css  js  c++  java
  • Codeforces 1229B. Kamil and Making a Stream

    传送门

    注意到只要考虑祖先和后代之间的贡献

    发现对于一个节点,他和所有祖先最多产生 $log$ 个不同的 $gcd$

    所以每个节点开一个 $vector$ 维护祖先到自己所有不同的 $gcd$ 和这个 $gcd$ 的出现次数即可

    之所以可以用 $vector$ 而不用 $set$ 是因为每个节点越祖先的节点下来的 $gcd$ 显然是越小的,存在单调性

    直接根据单调性从父亲的 $vector$ 小到大和自己的值 $gcd$ 并加入到自己的 $vector$ 里面,父亲的都加完后最后加入本身的值到 $vector$ 最后面即可

    因为每个节点最多有 $log$ 个不同的 $gcd$ ,所以复杂度是对的

    总复杂度 $O(n log (10^{12}))$

    当然用 $set$ 多一个 $log$ 应该也能过

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<vector>
    using namespace std;
    typedef long long ll;
    inline ll read()
    {
        ll x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=2e5+7,mo=1e9+7;
    int n;
    ll val[N];
    int fir[N],from[N<<1],to[N<<1],cntt;
    inline void add(int a,int b) { from[++cntt]=fir[a]; fir[a]=cntt; to[cntt]=b; }
    struct dat {
        ll d,cnt;
        dat (ll _d=0,ll _cnt=0) { d=_d,cnt=_cnt; }
    };
    vector <dat> V[N];
    inline ll gcd(ll a,ll b) { return b ? gcd(b,a%b) : a; }
    void dfs(int x,int fa)
    {
        if(fa)
            for(auto A: V[fa])
            {
                ll d=gcd(A.d,val[x]);
                if(V[x].empty() || V[x].back().d!=d)
                    V[x].push_back(dat(d,A.cnt));
                else V[x].back().cnt+=A.cnt;
            }
        if(V[x].empty() || V[x].back().d!=val[x])
            V[x].push_back(dat(val[x],1));
        else V[x].back().cnt++;
        for(int i=fir[x];i;i=from[i])
            if(to[i]!=fa) dfs(to[i],x);
    }
    int main()
    {
        n=read(); for(int i=1;i<=n;i++) val[i]=read();
        int a,b;
        for(int i=1;i<n;i++)
        {
            a=read(),b=read();
            add(a,b); add(b,a);
        }
        dfs(1,0); ll Ans=0;
        for(int i=1;i<=n;i++)
            for(auto A: V[i]) Ans=(Ans+A.d*A.cnt)%mo;
        printf("%lld
    ",Ans);
        return 0;
    }
  • 相关阅读:
    charles使用
    断言
    JDBC Request
    HTTP请求建立一个测试计划
    利用badboy进行脚本录制
    接口测试用例
    Monkey常用命令
    charles安装与使用
    celery配置与基本使用
    图片验证码接口
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/11580390.html
Copyright © 2011-2022 走看看