競技プログラミングの鉄則    次の問題へ    前の問題へ

B37 Sum of Digits


問題へのリンク


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("4");
            //10
        }
        else if (InputPattern == "Input2") {
            WillReturn.Add("288");
            //2826
        }
        else {
            string wkStr;
            while ((wkStr = Console.ReadLine()) != null) WillReturn.Add(wkStr);
        }
        return WillReturn;
    }

    static void Main()
    {
        List<string> InputList = GetInputList();
        long N = long.Parse(InputList[0]);

        // 0始まりにするので1足す
        long KouCnt = N + 1;

        long Answer = 0;

        // 10の指数でループ
        for (long I = 1; I <= N.ToString().Length; I++) {
            long CurrAnswer = 0;
            long[] CntArr = DeriveCntArr(I);

            // 群数列の群数列で、親群の項数を求める
            long OyaGunCnt = CntArr.Sum();

            // 群数列の群数列で、親群の数値合計を求める
            long OyaGunSum = 0;
            for (long J = 0; J <= CntArr.GetUpperBound(0); J++) {
                OyaGunSum += CntArr[J] * J;
            }
            //Console.WriteLine("OyaCnt={0},OyaSum={1}", OyaGunCnt, OyaGunSum);

            // 親群を何個持つか
            long DivCnt = KouCnt / OyaGunCnt;
            CurrAnswer += DivCnt * OyaGunSum;

            long RestCnt = KouCnt % OyaGunCnt;

            for (long J = 0; J <= CntArr.GetUpperBound(0); J++) {
                long MinusCnt = Math.Min(RestCnt, CntArr[J]);
                if (MinusCnt == 0) break;
                CurrAnswer += MinusCnt * J;

                RestCnt -= MinusCnt;
            }
            Answer += CurrAnswer;
        }
        Console.WriteLine(Answer);
    }

    // 10の指数を引数として、項数[値]な配列を返す
    static long[] DeriveCntArr(long pSisuu)
    {
        long Beki10 = 1;
        for (long I = 2; I <= pSisuu; I++) {
            Beki10 *= 10;
        }

        long[] CntArr = new long[10];
        for (long I = 0; I <= CntArr.GetUpperBound(0); I++) {
            CntArr[I] = Beki10;
        }
        return CntArr;
    }
}


解説

 0
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15

で
1の位の群数列
10の位の群数列
100の位の群数列
で桁ごとに分けて考えてます。