競技プログラミングの鉄則
次の問題へ
前の問題へ
B57 Calculator
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("10 1");
//0
//0
//0
//0
//0
//0
//0
//0
//0
//9
}
else {
string wkStr;
while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
}
return WillReturn;
}
static void Main()
{
List<string> InputList = GetInputList();
long[] wkArr = InputList[0].Split(' ').Select(pX => long.Parse(pX)).ToArray();
long N = wkArr[0];
long K = wkArr[1];
long UB = N;
// 現在の値[2べきの値]なDictの配列
var DoublingDictArr = new Dictionary<long, long>[UB + 1];
for (long I = 0; I <= UB; I++) {
DoublingDictArr[I] = new Dictionary<long, long>();
}
// 1回の変換後の値を設定
for (long I = 0; I <= UB; I++) {
DoublingDictArr[I][1] = I - DeriveKetaSum(I);
}
// 2べき回の変換後の値を設定
long Beki2 = 2;
while (Beki2 <= K) {
long Div2 = Beki2 / 2;
for (long I = 0; I <= UB; I++) {
long Div2Val = DoublingDictArr[I][Div2];
long GoalVal = DoublingDictArr[Div2Val][Div2];
DoublingDictArr[I][Beki2] = GoalVal;
}
Beki2 *= 2;
}
// 解を求める
var sb = new System.Text.StringBuilder();
for (long I = 1; I <= UB; I++) {
long CurrVal = I;
long RestCnt = K;
while (RestCnt > 0) {
long MaxBeki2 = DeriveMaxBeki2(RestCnt);
CurrVal = DoublingDictArr[CurrVal][MaxBeki2];
RestCnt -= MaxBeki2;
}
sb.Append(CurrVal);
sb.AppendLine();
}
Console.Write(sb.ToString());
}
// 数値を引数として、桁和を返す
static long DeriveKetaSum(long pTarget)
{
long WillReturn = 0;
while (pTarget > 0) {
WillReturn += pTarget % 10;
pTarget /= 10;
}
return WillReturn;
}
// 引数の数値以下で、最大の2べきを返す
static long DeriveMaxBeki2(long pTarget)
{
long WillReturn = 1;
for (long I = 1; I < long.MaxValue; I *= 2) {
if (I <= pTarget) {
WillReturn = I;
}
else {
break;
}
}
return WillReturn;
}
}
解説
ダブリングで解いてます。