zoukankan      html  css  js  c++  java
  • [题解] Luogu P6381 『MdOI R2』Odyssey

    https://www.luogu.com.cn/problem/P6381

    一个不怎么要脑子的做法...代码也不难写...

    考虑在DAG上DP

    (f_{i,j})表示以点(i)为结尾,且上一条边权值为(j)的最长路径数量。

    那么有转移

    (f_{v,b} = max { f_{u,a} + l })(ab=c^k)且存在边((u,v,w))

    先不管这样做的空间...

    考虑如何做到转移时满足(ab = c^k)这个条件

    (a)质因数分解:(a = p_1^{e_1}cdots p_s^{e_s})

    然后将所以指数对(k)取模,即令(e'_i = e_i mod k)

    然后得到一个数(a' = p_1^{e'_1} cdots p_s ^{e'_s})

    (b' = p_1^{k-e'_1} cdots p_s ^{k-e'_s})

    即对于(b)质因数分解后也做这样的操作可以得到(b')

    同时对于(a),与之匹配的(b)做这个操作后得到的(b')是唯一的,这也非常方便算出来。

    那么状态变一变,改成(f_{i,j'}),即以(i)结尾,上一条边做上述变换后得到的数为(j')时的最长路径。

    但数太大了,数组开不下,而且直接把数带进去也不好算

    注意到一个数的质因子个数不会太多,我们可以把他的质因数分解作为第二维(指数对(k)取模后的)然后DP。

    不想hash的话开个map记一下状态好了,DP就直接按拓扑序去转移

    具体还是看代码吧...

    跑的超慢的(Code):

    #include <bits/stdc++.h>
    using namespace std;
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    typedef pair<int,int> pii;
    typedef vector<pii> pfac;
    pfac factor(int n,int k)
    {
        pfac ans;
        for(int i=2;i*i<=n;i++)
        {
            int cnt=0;
            while(n%i==0) (++cnt)>=k?cnt-=k:0,n/=i;
            if(cnt) ans.pb(mp(i,cnt));
        }
        if(n>1&&k!=1) ans.pb(mp(n,1));
        return ans;
    }
    pfac mpfac(const pfac &pf,int k)
    {
        pfac ans;
        for (auto p:pf) ans.pb(mp(p.fi,k-p.se));
        return ans;
    }
    const int N=1111111;
    int n,m,k;
    struct edge
    {
        int u,v,w,l,nxt;
        pfac pf;
    }e[N];
    int fst[N],ec=0,ind[N],ans=0;
    void ade(int u,int v,int w,int l)
    {
        e[++ec]=(edge){u,v,w,l};
        e[ec].pf=factor(w,k);
        e[ec].nxt=fst[u],fst[u]=ec;
        ++ind[v];
        ans=max(ans,l);
    }
    int tps[N],tn;
    void topo()
    {
        tn=0;
        queue<int> q;
        for(int i=1;i<=n;i++) if(ind[i]==0) q.push(i);
        while(q.size())
        {
            int u=q.front(); q.pop();
            tps[++tn]=u;
            for(int i=fst[u];i;i=e[i].nxt)
            {
                int v=e[i].v; --ind[v];
                if (ind[v]==0) q.push(v);
            }
        }
    }
    map<pfac,int> f[N];
    void dp()
    {
        for(int i=1;i<=tn;i++)
        {
            int u=tps[i];
            for(int j=fst[u];j;j=e[j].nxt)
            {
                int v=e[j].v;
                pfac pf=e[j].pf,mpf=mpfac(pf,k);
                f[v][mpf]=max(f[v][mpf],f[u][pf]+e[j].l);
                ans=max(ans,f[v][mpf]);
            }
        }
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        for(int i=1,u,v,w,l;i<=m;i++)
            scanf("%d%d%d%d",&u,&v,&w,&l),ade(u,v,w,l);
        topo(),dp();
        printf("%d
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    struts2 s:if 的字符串比较问题
    struts2 标签
    servlet filter
    div滚动与控制
    页面定位
    linux下编译利用CMakeLists.txt 编译C++写的opencv程序
    yolo image.c
    强制杀进程
    PDB GDB 调试代码
    YOLOv3的Darknet在OpenCV3.4.1(bug)下编译出错填坑
  • 原文地址:https://www.cnblogs.com/wxq1229/p/12939317.html
Copyright © 2011-2022 走看看