トップページに戻る
次の競技プログラミングの問題へ
前の競技プログラミングの問題へ
ABC-007-D 禁止された数字
■■■問題■■■
たかはし王国の国王であるたかはし君主は数字の4と9が大嫌いです。
それらの数字を国内で目にするだけで気分が悪いので、それらを使ってはいけないという法律を定めました。
この法律を破ってしまうと罰せられます。
数字が禁止されているので、ある数の10進表現を考えたとき、
いずれかの桁に禁止された数字が1つでも含まれている場合、その数を使うことはできません。
今まで使っていた数字を使えなくなったあなたは、うっかり使ってしまって罰せられては困るので、
使う可能性がある数の区間 [A,B]={A,A+1,A+2, ・・・ ,B} に、
いくつ禁止された数が含まれているかを確かめることにしました。
そのためのプログラムを作ってください。
■■■入力■■■
A B
1行目には、整数 A,B (1 <= A <= B <= 10の18乗) が空白区切りで与えられる。
■■■出力■■■
区間 [A,B] に含まれる禁止された数がいくつ含まれているかを1行に出力せよ。
出力の末尾に改行をいれること。
C#のソース
using System;
using System.Collections.Generic;
using System.Linq;
class Program
{
static string InputPattern = "InputX";
static List<string> GetInputList()
{
var WillReturn = new List<string>();
if (InputPattern == "Input1") {
WillReturn.Add("1 9");
//2
//4と9が禁止されています。
}
else if (InputPattern == "Input2") {
WillReturn.Add("40 49");
//10
//40から49は全て禁止された数です。
}
else if (InputPattern == "Input3") {
WillReturn.Add("1 1000");
//488
}
else if (InputPattern == "Input4") {
WillReturn.Add("1 1000000000000000000");
//981985601490518016
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
string[] wkArr = InputList[0].Split(' ');
string A = wkArr[0];
string B = wkArr[1];
long CntA = ExecDP(A);
long CntB = ExecDP(B);
long CntCommon = 0;
if (A.Contains('4') || A.Contains('9'))
CntCommon = 1;
Console.WriteLine(CntB - CntA + CntCommon);
}
//0から引数までの4または9を含んだ数の個数を返す
static long ExecDP(string pStr)
{
//場合の数[4または9の存在フラグ,数字自由フラグ]なDP表
long[,] PrevDP = new long[2, 2];
PrevDP[0, 0] = 1;
for (int I = 0; I <= pStr.Length - 1; I++) {
long[,] CurrDP = new long[2, 2];
for (int J = 0; J <= 1; J++) {
for (int K = 0; K <= 1; K++) {
if (PrevDP[J, K] == 0) continue;
for (char NewChar = '0'; NewChar <= '9'; NewChar++) {
if (K == 0 && pStr[I] < NewChar) break;
int NewJ = J;
if (NewChar == '4') NewJ = 1;
if (NewChar == '9') NewJ = 1;
int NewK = K;
if (pStr[I] > NewChar) NewK = 1;
CurrDP[NewJ, NewK] += PrevDP[J, K];
}
}
}
PrevDP = CurrDP;
}
long Answer = 0;
Answer += PrevDP[1, 0];
Answer += PrevDP[1, 1];
return Answer;
}
}
解説
桁DPで解いてます。