トップページに戻る    次の競技プログラミングの問題へ    前の競技プログラミングの問題へ

東工大プロコン2015 D 文字列と素数

■■■問題■■■

文字列Sが与えられる。以下の条件を満たす変換でSからある数への変換を行う。

●Sの各文字を1,3,5,7,9のいずれかの数字に変換する。
●同じ文字は同じ数字に、異なる文字は異なる数字に変換しなくてはならない。

上の条件を満たす変換によって、文字列Sを素数に変換することできるだろうか。

■■■入力■■■

S

●1行で文字列 S(1 <= |S| <= 10)が与えられる。
●Sの各文字は、英小文字である。

■■■出力■■■

素数の変換先を得られる場合は、そのような素数を1つ出力してください。
素数の変換先がない場合は、-1を出力してください。

素数の変換先が複数ある場合は、いずれを出力しても正解として扱われる。


C#のソース

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

class Program
{
    static string InputPattern = "Input1";

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

        if (InputPattern == "Input1") {
            WillReturn.Add("tit");
            //131
            //他にも、151,171,191,313,・・・ のいずれかを出力しても正解として扱われる
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("titech");
            //757319
        }
        else if (InputPattern == "Input3") {
            WillReturn.Add("tokyotech");
            //-1
            //文字の種類が多すぎるため、条件を満たす変換を構成することができません
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    struct JyoutaiDef
    {
        internal string CurrStr;
    }

    static void Main()
    {
        List<string> InputList = GetInputList();
        string S = InputList[0];

        if (S.Distinct().Count() > 5) {
            Console.WriteLine(-1);
            return;
        }

        char[] NumArr = { '1', '3', '5', '7', '9' };

        var stk = new Stack<JyoutaiDef>();
        JyoutaiDef WillPush;
        WillPush.CurrStr = S;
        stk.Push(WillPush);

        while (stk.Count > 0) {
            JyoutaiDef Popped = stk.Pop();

            int wkInd = Array.FindLastIndex(Popped.CurrStr.ToCharArray(), X => X < '1' || '9' < X);

            //クリア判定
            if (wkInd == -1) {
                if (IsPrime(long.Parse(Popped.CurrStr))) {
                    Console.WriteLine(Popped.CurrStr);
                    return;
                }
                continue;
            }

            foreach (char EachChar in NumArr) {
                if (Popped.CurrStr.Contains(EachChar)) continue;

                //枝切り 2桁以上の数であれば、末尾に5は使えない
                if (S.Length >= 2 && wkInd == S.Length - 1 && EachChar == '5')
                    continue;

                char wkChar = Popped.CurrStr[wkInd];
                WillPush.CurrStr = Popped.CurrStr.Replace(wkChar, EachChar);
                stk.Push(WillPush);
            }
        }
        Console.WriteLine(-1);
    }

    //試し割りで素数かを判定
    static bool IsPrime(long pTarget)
    {
        if (pTarget == 2) return true;
        if (pTarget % 2 == 0) return false;
        for (long I = 3; I * I <= pTarget; I += 2) {
            if (pTarget % I == 0) return false;
        }
        return true;
    }
}


解説

1,3,5,7,9 で5!で120通りしかないうえに、
1桁目が5の場合を枝切りすれば、
4*4*3*2で96通りですので、DFSで全探索してます。