16進法では, 数は以下の16個の数字によって表される 0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F 16進数の AF は, 10進法での 10*16 + 15 = 175 と等しい. 3桁の16進数 10A, 1A0, A10, A01 には, 0, 1, A の全てが現れている. 10進数で書くときと同様に, 先頭の0は書かないことにする. 0, 1, A がそれぞれ少なくとも1回は現れるような16桁までの16進数はいくつ存在するか? 16進数で答えよ. (A,B,C,D,E,F は大文字とし, 先頭や末尾の16進数であることを表す記号や先頭の0は許されない. つまり, 1A3F ならOK. 1a3f, 0x1a3f, $1A3F, #1A3F, 0000001A3Fは許されない. )
using System; using System.Collections.Generic; class Program { const int KetaSuu = 16; struct JyoutaiDef { internal bool Has0; internal bool Has1; internal bool HasA; internal bool IsAppearNonZero; } static string GetHash(JyoutaiDef pJyoutai) { var sb = new System.Text.StringBuilder(); sb.Append(pJyoutai.Has0 ? '1' : '0'); sb.Append(pJyoutai.Has1 ? '1' : '0'); sb.Append(pJyoutai.HasA ? '1' : '0'); sb.Append(pJyoutai.IsAppearNonZero ? '1' : '0'); return sb.ToString(); } static JyoutaiDef GetJyoutai(string pHash) { JyoutaiDef WillReturn; WillReturn.Has0 = pHash[0] == '1'; WillReturn.Has1 = pHash[1] == '1'; WillReturn.HasA = pHash[2] == '1'; WillReturn.IsAppearNonZero = pHash[3] == '1'; return WillReturn; } static void Main() { //場合の数[状態のハッシュ値]なDP表 var PrevDP = new Dictionary<string, long>(); PrevDP.Add("0000", 1); for (int I = 1; I <= KetaSuu; I++) { var CurrDP = new Dictionary<string, long>(); foreach (var EachPair in PrevDP) { for (int J = 0; J <= 15; J++) { JyoutaiDef CurrJyoutai = GetJyoutai(EachPair.Key); if (CurrJyoutai.IsAppearNonZero && J == 0) CurrJyoutai.Has0 = true; if (J == 1) CurrJyoutai.Has1 = true; if (J == 10) CurrJyoutai.HasA = true; if (J != 0) CurrJyoutai.IsAppearNonZero = true; string NewKey = GetHash(CurrJyoutai); if (CurrDP.ContainsKey(NewKey)) CurrDP[NewKey] += EachPair.Value; else CurrDP[NewKey] = EachPair.Value; } } PrevDP = CurrDP; } long Answer = 0; foreach (var EachPair in PrevDP) { JyoutaiDef wkJyoutai = GetJyoutai(EachPair.Key); if (wkJyoutai.Has0 == false) continue; if (wkJyoutai.Has1 == false) continue; if (wkJyoutai.HasA == false) continue; Answer += EachPair.Value; } Console.WriteLine("10進数だと、{0}個", Answer); Console.WriteLine("16進数だと、{0}個", Answer.ToString("X")); } }
10進数だと、4420408745587516162個 16進数だと、3D58725572C62302個
桁DPで解いてます。