いくつかのCodeforces 747Fイゴールと興味深い数字DPの組み合わせ

質問の意味:あなたの番号を与え、nおよびTには、数t以下で表示されない、n個の小さな最初進数がある文字を尋ねました。

アイデア:デジタルDPを考えるのは簡単、しかし、ではありません。私たちは、後の裁判で見つけると方法を埋めるためにどのように多くのビットを知っているどのように多くのビットを知っている必要があります。私たちは、手紙、いくつかのプログラムのI種類がj番目の位置を占めてきた前に考慮すべきDP [i]の[j]を設定します。次にDP [I] [J] + = DP [I - 1] [J - K] * C [LEN - J + K] [K]、k個の範囲[0、上限は[] K]。我々は、i番目の暴力は、文字、および順列と組み合わせの数を入れて列挙意味。

問題は必ずしものでアップゼロに、細部に注意を払う必要があるので、私たちはその後、失うものは事前に数0のすべてのための最高レベルに直接記入時間は、最上位ビットをスキップ埋めるためにしようとしようとすることができます0の状況です。どれだけでも道を見つけるために少しの時間で0ビットの全ての数が最も多いです。

コード:

#include <ビット/ STDC ++ Hが> 
の#define LL長い長い
名前空間stdを使用。
INT制限[20]。
LL C [20] [20]、DP [20] [20]。
アウト無効(int型X){ 
	IF(X <10)のprintf( "%d個"、X)。
	他のprintf( "%のC"、X - 10 + '')。
} 
(INT LEN、INTフラグ)を解くLL { 
	IF(LEN == 0)リターン1。
	memsetの(DP、0、はsizeof(DP))。
	以下のために(INT i = 0; iが<= LEN && iが<=リミット[0]; iは++)
		DP [0] [I] = C [LEN] [I]。
	以下のために(INT i = 1; iは<16; I ++)
		のための(INT J = 0であり、j <= lenを; J ++){ 
			ための(int型のk = 0; K <= J && K <=リミット[I]; ++ K) { 
				DP [I] [J] + = DP [I - 1] [J - K] * C [LEN - J + K] [K]。
			} 
		} 
	戻りDP [15] [LEN]。		
INTメイン(){ 
	LL nを、ANS。
	int型メートル。
	scanf関数( "%のLLD%dの"、&N、&M)。
	ANS = N。
	以下のために(INT i = 0; iは16 <; I ++)制限を[I] = mを、
	ための式(I = 0 int型、iは<= 15; I ++)C [i]が[0] = 1; 
	ための式(I = 1 int型、iは<= 15; I ++)
		のための(INT J = 1; J <= I; J ++)
			C [I] [J] = C [I - 1] [J - 1] + C [ I - 1] [J]。
	int型のPOS = -1; 
	以下のために(INT i = 0; I> = 0; I ++){ 
		LLのTMP = 0。
		(INT J = 1; J <16; J ++){ため
			リミット[J] - 。
			TMPは+ =(i、j)を解きます。
			リミット[J] ++; 
			IF(TMP> = ANS){ 
				POS = I。
				ブレーク; 
			} 
		} 
		もし(TMP> = ANS)ブレーク。
		他のANS - = TMP;
	} 
	N = ANS。
	以下のために(私は= POS int型; I> = 0; i--){ 
		ための(int型J = 0であり、j <16; J ++){ 
			(I == POS && J == 0)が続く場合、
			(リミット[J] == 0)が継続する場合。
			リミット[J] - 。
			LL TMPは=(i、j)を解きます。
			リミット[J] ++; 
			(TMP <N){もし
				N - = TMP。
			}他{ 
				RES [i]のjは=。
				リミット[J] - 。
				ブレーク; 
			} 
		} 
	} 
	のための(I = POS int型; I> = 0; i--){ 
		OUT(RES [I])。
	} 
	のprintf( "の\ n"); 
}

  

おすすめ

転載: www.cnblogs.com/pkgunboat/p/11094467.html