2025-01-11-16-48


using System;
using System.Collections.Generic;
using System.Linq;

// https://atcoder.jp/contests/past202005-open/tasks/past202005_o
class Program
{
    static string InputPattern = "Input1";

    static List<string> GetInputList()
    {
        var WillReturn = new List<string>();

        if (InputPattern == "Input1") {
            WillReturn.Add("2 1");
            WillReturn.Add("3 2");
            WillReturn.Add("3 3");
            WillReturn.Add("100000 100000 100000");
            //81
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("4 2");
            WillReturn.Add("2 4 3 3");
            WillReturn.Add("4 2 3 3");
            WillReturn.Add("100000 100000 100000");
            //210
        }
        else if (InputPattern == "Input3") {
            WillReturn.Add("20 19");
            WillReturn.Add("3 2 3 4 3 3 2 3 2 2 3 3 4 3 2 4 4 3 3 4");
            WillReturn.Add("2 3 4 2 4 3 3 2 4 2 4 3 3 2 3 4 4 4 2 2");
            WillReturn.Add("3 4 5");
            //-1417
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    class EdgeInfoDef
    {
        internal long ToNode;
        internal long Capacity;
        internal long Cost;
        internal long Flow;
    }
    static Dictionary<long, List<EdgeInfoDef>> mEdgeInfoListDict = new Dictionary<long, List<EdgeInfoDef>>();

    static void Main()
    {
        List<string> InputList = GetInputList();

        long[] wkArr = { };
        Action<string> SplitAct = pStr =>
            wkArr = pStr.Split(' ').Select(pX => long.Parse(pX)).ToArray();

        SplitAct(InputList[0]);
        long N = wkArr[0];
        long M = wkArr[1];

        long[] AArr = InputList[1].Split(' ').Select(pX => long.Parse(pX)).ToArray();
        long[] BArr = InputList[2].Split(' ').Select(pX => long.Parse(pX)).ToArray();

        SplitAct(InputList.Last());
        long R1 = wkArr[0];
        long R2 = wkArr[1];
        long R3 = wkArr[2];

        var NodeNameList = new List<string>();

        NodeNameList.Add("R1");
        NodeNameList.Add("R2");
        NodeNameList.Add("R3");

        for (long I = 1; I <= N; I++) {
            NodeNameList.Add("棒" + I.ToString());
        }

        NodeNameList.Add("Source");
        NodeNameList.Add("Sink");

        // ノードID[ノード名]なDict
        var NodeIDDict = new Dictionary<string, long>();
        foreach (string EachStr in NodeNameList) {
            NodeIDDict[EachStr] = NodeIDDict.Count;
        }
        long UB = NodeIDDict.Count - 1;

        Action<long, long, long, long> AddEdgeAct = (pFromNode, pToNode, pCapacity, pCost) =>
        {
            if (mEdgeInfoListDict.ContainsKey(pFromNode) == false) {
                mEdgeInfoListDict[pFromNode] = new List<EdgeInfoDef>();
            }
            var WillAdd = new EdgeInfoDef();
            WillAdd.ToNode = pToNode;
            WillAdd.Capacity = pCapacity;
            WillAdd.Cost = pCost;
            WillAdd.Flow = 0;
            mEdgeInfoListDict[pFromNode].Add(WillAdd);
        };

        AddEdgeAct(NodeIDDict["Source"], NodeIDDict["R1"], M, 0);
        AddEdgeAct(NodeIDDict["Source"], NodeIDDict["R2"], M, 0);
        AddEdgeAct(NodeIDDict["Source"], NodeIDDict["R3"], M, 0);
        AddEdgeAct(NodeIDDict["R1"], NodeIDDict["Source"], 0, 0);
        AddEdgeAct(NodeIDDict["R2"], NodeIDDict["Source"], 0, 0);
        AddEdgeAct(NodeIDDict["R3"], NodeIDDict["Source"], 0, 0);

        for (long I = 1; I <= 3; I++) {
            long FromNode = NodeIDDict["R" + I.ToString()];
            for (long J = 1; J <= N; J++) {
                long ToNode = NodeIDDict["棒" + J.ToString()];

                long Syokou = AArr[J - 1];
                long Kouhi = BArr[J - 1];

                long Cost = Syokou * Kouhi;
                for (long K = 1; K <= I; K++) {
                    Cost *= Kouhi;
                }
                long Hou = R1;
                if (I == 2) Hou = R2;
                if (I == 3) Hou = R3;

                AddEdgeAct(FromNode, ToNode, 1, -1 * (Cost % Hou));
                AddEdgeAct(ToNode, FromNode, 0, +1 * (Cost % Hou));
            }
        }

        for (long I = 1; I <= N; I++) {
            long FromNode = NodeIDDict["棒" + I.ToString()];

            long Syokou = AArr[I - 1];
            long Kouhi = BArr[I - 1];

            long Cost = Syokou * Kouhi;
            var CostList = new List<long>();
            for (long J = 1; J <= 3; J++) {
                Cost *= Kouhi;
                CostList.Add(Cost);
            }

            for (int J = 0; J <= CostList.Count - 1; J++) {
                long CurrCost = CostList[0];
                if (J == 1) {
                    CurrCost = CostList[1] - CostList[0];
                }
                if (J == 2) {
                    CurrCost = CostList[2] - CostList[1] - CostList[0];
                }
                AddEdgeAct(FromNode, NodeIDDict["Sink"], 1, +CurrCost);
                AddEdgeAct(NodeIDDict["Sink"], FromNode, 0, -CurrCost);
            }
        }

        // 逆辺と正辺で二重辺が存在しうるので、コストの昇順にソートしておく
        foreach (var EachPair in mEdgeInfoListDict) {
            EachPair.Value.Sort((pA, pB) => pA.Cost.CompareTo(pB.Cost));
        }

        long RestFlow = M * 3;

        while (RestFlow > 0) {
            var NodeList = BellmanFord(NodeIDDict["Source"], NodeIDDict["Sink"]);
            if (NodeList == null) {
                Console.WriteLine(-1);
                return;
            }

            Console.WriteLine("経路を発見しました");
            NodeList.ForEach(pX => Console.Write("{0},", pX));
            Console.WriteLine();

            // 経路でのCapacityの最小値を求める
            var CapacityList = new List<long>();
            for (int I = 0; I <= NodeList.Count - 2; I++) {
                long FromNode = NodeList[I];
                long ToNode = NodeList[I + 1];

                foreach (EdgeInfoDef EachEdgeInfo in mEdgeInfoListDict[FromNode]) {
                    if (EachEdgeInfo.ToNode != ToNode) continue;
                    // 二重辺が存在しうるので、Capacityが0ならcontinue
                    if (EachEdgeInfo.Capacity == 0) continue;
                    CapacityList.Add(EachEdgeInfo.Capacity);
                    break;
                }
            }
            long CurrFlow = Math.Min(RestFlow, CapacityList.Min());
            Console.WriteLine("この経路に{0}の水を流します", CurrFlow);

            // フローを流して、逆辺を作る
            for (int I = 0; I <= NodeList.Count - 2; I++) {
                long FromNode = NodeList[I];
                long ToNode = NodeList[I + 1];

                // フローを流す
                foreach (EdgeInfoDef EachEdgeInfo in mEdgeInfoListDict[FromNode]) {
                    if (EachEdgeInfo.ToNode != ToNode) continue;
                    // 二重辺が存在しうるので、Capacityが0ならcontinue
                    if (EachEdgeInfo.Capacity == 0) continue;
                    EachEdgeInfo.Capacity -= CurrFlow;
                    EachEdgeInfo.Flow += CurrFlow;
                    break;
                }

                // 逆辺を作る
                foreach (EdgeInfoDef EachEdgeInfo in mEdgeInfoListDict[ToNode]) {
                    if (EachEdgeInfo.ToNode != FromNode) continue;
                    EachEdgeInfo.Capacity += CurrFlow;
                    break;
                }
            }
            RestFlow -= CurrFlow;
        }

        // コストを計算する
        long Answer = 0;
        foreach (List<EdgeInfoDef> EachEdgeList in mEdgeInfoListDict.Values) {
            foreach (EdgeInfoDef EachEdgeInfo in EachEdgeList) {
                Answer += EachEdgeInfo.Flow * EachEdgeInfo.Cost;
            }
        }
        Console.WriteLine(Answer);
    }

    // ベルマンフォードで、最小コストな経路を返す
    static List<long> BellmanFord(long pStaNode, long pGoalNode)
    {
        // どのノードから来たかのDict
        var PrevNodeDict = new Dictionary<long, long>();

        //各ノードまでの距離のDict
        var SumCostDict = new Dictionary<long, long>();
        SumCostDict[pStaNode] = 0;

        // 頂点数だけループ
        bool WillBreak = false;
        for (long I = 1; I <= int.MaxValue; I++) {
            WillBreak = true;

            foreach (long EachKey in SumCostDict.Keys.ToArray()) {
                if (mEdgeInfoListDict.ContainsKey(EachKey) == false)
                    continue;

                // そのノードから訪問可能なノードで
                // 最短距離を更新可能なら更新
                foreach (EdgeInfoDef EachNodeInfo in mEdgeInfoListDict[EachKey]) {
                    if (EachNodeInfo.Capacity == 0) continue;

                    long wkSumCost = SumCostDict[EachKey] + EachNodeInfo.Cost;
                    if (SumCostDict.ContainsKey(EachNodeInfo.ToNode)) {
                        if (SumCostDict[EachNodeInfo.ToNode] <= wkSumCost) {
                            continue;
                        }
                    }
                    SumCostDict[EachNodeInfo.ToNode] = wkSumCost;
                    PrevNodeDict[EachNodeInfo.ToNode] = EachKey;
                    WillBreak = false;
                }
            }
            if (WillBreak) break;
        }

        if (SumCostDict.ContainsKey(pGoalNode) == false) {
            return null;
        }

        var NodeList = new List<long>();
        long CurrNode = pGoalNode;
        while (true) {
            NodeList.Add(CurrNode);
            if (CurrNode == pStaNode) break;
            CurrNode = PrevNodeDict[CurrNode];
        }
        NodeList.Reverse();
        return NodeList;
    }
}