[週末のトレーニング]デジタルカウント

タイトル

[メモリの制限:$ 512MiB $]  [制限時間:$ 1000ミリ秒$]
O [規格]   [タイトルタイプ:伝統]   [評価方法:テキストの比較]

説明[タイトル]

ZJOI 2010:オリジナルタイトルから

2つの正の整数を考えるには、$と$ B $を$ [a、b]は$ $求めて、すべての整数の、各デジタル$(数字)$それぞれが何回も登場します。

[入力形式]

行が2つだけの整数を含む  、意味は上記に示しました。

[出力形式]

$ 10 $ラインが含まれ、それぞれ、$ 9 $ 0~整数を$で$を[a、b]でで何度も表示されます。

[サンプル]

サンプル入力

1  99

サンプル出力

9  20  20  20  20  20  20  20  20  20

[データ範囲]

$ 30%の$のデータは、[1,10 ^ 6] $で、bは\を$

$ 100%$のデータは、[1,10 ^ {12}] $において、B \を$


 

問題の解決策

[体験]のタイトルを行います

問題を解決するとき、教師はそれが$ DPの$のタイトルだったと述べていない場合、私はまた、嵐の上で直接検索することが私の最後の嵐はまた、正のソリューションコードを発見したものの、

まず、私が見つかりました。プッシュデータのビットまたはマルチミスを試してみましたが、いつもこのタイトルと$ DPの$の間の接続が何であるか見当がつかない。

その後、私のスミアの2

【正解】

これは、デジタル$ DPの$のタイトルです

谷に散歩に数回は、まだ書くために兄を見つけ$ $正ソリューションDP (ORZ崇拝ギャング)が、私は$ DP $の起源を理解していない、かなり愚かだ(私のこんにゃくの$のDP $意志このよう)に、涙が、彼女は検索の練習を発見しました。

まず、我々がそれに問題を入れて、行うキー・ルの約束の数と同じように、区間$ [a、b]は$は間隔の$となりの要求の対象[1、B]インターバルの$ [1 $、A- 1]デジタル数の$が生じます。

今、私たちは、解決しなければならないデジタルの各番号$の出現の区間$ [1、k]を見つける方法です。

私はそれの$のDFSの$の部分を見て

INT DFS(INT LEN、BOOL小さい、int型の和、BOOL prezero、INT D){
     場合(LEN == 0戻り和。int型 RET = 0 ;
    以下のためにint型 i = 0 ; iは< 10 ; ++ I){
         場合(小&& I> NUM [LEN])破ります
        RET + = DFS(len- 1、小さな&&(I == NUM [LEN])、合計+((!prezero || I> 0)&&(I == D))、prezero &&(I == 0 )、D) ; 
    } 
    戻り RET。
}

$のDFSの$感が非常に明確で、ああではありません。

ケケは、私が説明します、$のDFS $は5つのパラメータで構成され、それらは:

  • $レン$:の数を列挙するいくつかの最初の
  • $小$:右側の境界に対応する数字に等しい未満の必要性
  • $合計$:もちろん、例数は既に存在しています
  • $ Prezero $:大手$ 0 $と番号の現在の構造かどうか
  • $ Dが$:デジタル現在のお問い合わせ

小さな$が理解し少し難しいかもしれ、ここでは例を与えることができます$そのうち

我々は右の境界の$ K = 1388 $と仮定します

私たちの数の現在の構造は、$のNum = \ {上線13ix} $($ X $は、我々はビット数を列挙する必要はありません)であります

右側の境界よりもそれ以外の場合は$のNum $より明らかに、$i≤8$、

そして、それは$小さな$の有用性です

この問題を解決するため、次の質問があり、検索に直面するだろう - 時間の複雑さを

コードが裸のクロスであれば当然、飛ぶように$ T $となります

だから我々は繰り返し検索操作のほとんどを減らすためにメモリを追加する必要があります

そして、ここで実際にはすべてのパラメータのメモリだけで(非常に優しいこの範囲のタイトルとして)定義にし、その上にインデックス全体を検索する必要があり

次いで、対応する検索パラメータで定義されている$ DP [LEN] [小] [和] [prezero] $のメモリがあります

我々は、サブワード検索されているので、最後の1次元は省略することができるので

その後、コードはあなたの好みであります

#include <ビット/ STDC ++ H>
 使用して 名前空間STDを、
#defineは長いlong int型
テンプレート < クラス T>インラインボイド qread(T&X){
     チャー Cと、BOOL F =  ; X = 0 一方、((C = GETCHAR())< ' 0 ' || ' 9 ' <c)の場合(C == ' - ')、F = (X =(C ^ 48)、' 0 ' <=(C = GETCHAR())&& C <9 ' ; X =(X << 1)+(X << 3)+(C ^ 48 ))。
    もし(F)X = - X。
} 
テンプレート < クラス T、クラス ...のArgs>インラインボイド qread(T&X、Argsの&...引数){qread(X)、qread(引数...);} 
インラインINT rqread(){
     チャー C。ブール値 F =  ; INT X = 0 一方、((C = GETCHAR())< ' 0 ' || ' 9 ' <c)の場合(C ==' - ')、F = (X =(C ^ 48)、' 0 ' <=(C = GETCHAR())&& C <= ' 9 ' ; X =(X << 1)+(X << 3)+(C ^ 48 ) );
    リターン?F - X:X; 
} 
のconst  int型 MAXSIZE = 20 int型の L、R、NUM [MAXSIZE + 5 ]。
INT DP [MAXSIZE + 5 ] [ 2 ] [MAXSIZE + 5 ] [ 2 ]。
int型 DFS(int型LEN、BOOL小さい、int型の和、BOOL prezero、int型のD){
     場合(LEN == 0戻り和。
    もし(DP [LEN] [小] [和] [prezero] =! - 1戻りDP [LEN] [小] [和] [prezero]。
    int型 RET = 0 ;
    以下のためにint型 i = 0 ; iは< 10 ; ++ I){
         場合(小&& I> NUM [LEN])破ります
        RET + = DFS(len- 1、小さな&&(I == NUM [LEN])、合計+((!prezero || I> 0)&&(I == D))、prezero &&(I == 0 )、D)。
    } 
    戻り DP [LEN] [小] [和] [prezero] =のRET。
} 
インラインINTは(解決int型の VARint型D){
     int型 LEN = 0 
    memsetの(DP、 - 1はsizeof DP)。
    一方、VAR)NUM [++ LEN = VARの10VAR / = 10 戻り DFS(LEN、101 、d)を、
}
{main()の符号付き
//     freopenは(STDIN、 "R"、 "です。");
//     freopenは(、 "W"、stdoutを"アウト。"); 
    qread(L、R)。
    以下のためにint型 i = 0 ; iは< 10 ; ++ I)のprintf(" %のLLD "、(1-(R、I)-solveを解決する1 I)、)。
    putchar(' \ nを' );
    リターン 0 ; 
}

おすすめ

転載: www.cnblogs.com/MachineryCountry/p/11612360.html