オリジナル:Hのttps://www.luogu.org/problemnew/solution/P1018ページ= 7?
トピック:P1019 [製品]最大
はじめに:
- この問題に対するポジティブなソリューションは、理論的にDP、しかしであると言われているので、プライベートデータは、あまりにも多くの水ではなく、使用するにはあまりにも難しい暴力
全体的なアイデア:
- それぞれがセグメント化されたか否かのフラグ(接続用、0分割)を用いてBアレイ。
- Bはnext_permutationのSTLを使用して、様々な置換(すなわち、暴力列挙それぞれの場合)を取得します。
- 大規模なデータの問題として、そう各部門の最終結果の高精度計算を使用し、最大値を見つけること。
next_permutation機能:
- つまり、ある要求STL 完全なアレイ機能、それ以外の場合は、配列のすべて見つけることができません(このように構成され、それは方法に関連するグループ生成)通常通り、next_permutationをソート、2つのパラメータは、それぞれ存在する、昇順でなければならないアレイを尋ねますこれは、最初のアドレス、アレイの終了アドレスであり、ブール量を返し、すなわち、次の完全な配列は、次いで、1つの2 3の構成として、指定された配列にtrueを返し、次の配列できるか否かを判断します132です。
コードの場合:
#include <アルゴリズム> // 使用next_permutation呼び出す必要ヘッダ の#include <cstdioを> // C言語読み取る出力 する#include <CStringの> // 高精度の加工文字列を使用する必要 使用して 名前空間はstdを、 構造体 BigN { // 精度(すなわち、大整数)計算 INT NUM [ 1001 ] = { 0 }、lenの; BigN(CHAR S []) // 大きな整数割り当ての新しい定義のコンストラクタ { LEN = STRLEN(S)。 用(INT I = len- 1 ; I> = 0 ; i-- ) NUM [I] = S [lenの-I- 1 ] - ' 0 ' 。 } 空クリーン() // クリアのための { memset(NUM、0、はsizeof (NUM))。 } ボイド F(INT N-) // 通常の整数大きい整数の先頭に押圧され、分割たびに、後で使用される { ため(INT I = LEN; I> 0 ; i-- ) 確かに、[I] = NUM [I- 1 ]。++ ; 確かに[ 0 ] = N。 } 空チェン(N-BigN)// 精度乗算、説明するにはあまりにも多くはありません、あなたはP1303に行くことができる質問があり、より学びます { BigN C(" 0 " )。 INT S = 0、G = 0 。 以下のために(int型私は= 0 ; I <= LEN; I ++ ) のための(int型 J = 0 ; J <= n.lenあり、j ++ ) { int型 = I + W jを。 S = NUM [I] * n.num [J]。 c.num [W] + = S%10 。 c.num [N + 1 ] = A + / 10 + c.num [W] / 10 。 c.num [W]%= 10 。 } c.len = +としてn.len。 一方、(c.num [c.len] == 0 && c.len> = 0)c.len-- 。 FZ(C); } ボイド FZ(N-BigN)// 大きい整数に大きな整数の例外は、「=」と等価です { LEN = n.len。 以下のために(int型私は= 0 ; I <= n.len; I ++ ) 確かに、[I] = n.num [I]。 } BOOL BJ(N-BigN) // 二つの大きな整数のサイズ、最大値を見つけるための結果を決定 { IF(LEN> n.len) リターン 1。; 他 IF(LEN < n.len) 戻り 0 ; 他 { 用(INT I = LEN; I> = 0 ; i-- ) 場合(NUM [I] < n.num [i])と リターン 0 。 それ以外の 場合(NUM [I]> n.num [i])と リターン 1 。 リターン - 1 。 } } 空 OUT()// 出力 { のために(int型 I = LEN; I> = 0 ; i-- ) printf(" %dの" 、NUM [I])。 } }。 INT N-、K、SUM [ 55 ]、B [ 55 ]、I、J; // 従来の定義、説明するために多くを行う BigN Mmaxをする(" 0 " )。 int型のmain() { チャー S [ 101 ]; // Sを大きな整数読み取るための scanfのを(" %D%D%S "、&N-、&K&S); のため(私は= 0 ; I <strlenを(S); I ++) // の和で元の数のコピーを保つ -和[I] = S [I]が' 0 ' ; のための(I = N- 2 ; I> =(NK) - 。1 ; i--) // 配列b必要が配列next_permutationの上昇を使用するか、すべての構成を見つけることができないかもしれないので、ポスト1に割り当てられた番号k Bを[I] = 1 ; 行い{ TEMP BigN(" 0 ")、全て(" 1 "); // 各セクションを分割するための保存後TEMP、各配置のためのすべての結果 私は= 0 ; ながら(I <N-)// スプリット { IF(I!= 0 ) IF(B [I- 1 ] == 1)// Bの場合、[I-1] 1で、その後、彼らはすぐに、この1プラス乗算記号で区分の元の数を持っているでしょう all.cheng(TEMP)、temp.clean(); // 次のセクションを記憶するために、分割の数字、空の温度を乗算の数 temp.f(SUM [I])、I ++; / / トップの温度に圧力下で元の数 } all.cheng(TEMP); // 温度によりそれほど再び、すべてのループ終了を取るしていないので、 IF(mmax.bj(すべて)== 0)// 順序前に、この結果がより大きい場合、最大結果リフレッシュ最大結果 mmax.fz(すべて); } 一方(next_permutation(B、B + N- 1)); // コールnext_permutation 。MmaxをOUT(); // 出力 戻り 0 ; }