トピックへのリンク:https://www.lydsy.com/JudgeOnline/problem.php?id=1072
[(J * 10 + [K])|形状圧DP、DPは、[I] [j]は状態iは、DのI jはプログラムの数としていることを示し、[(1 << k)のi]が存在DP %のD] + = DP [I]、[J]、kは状態で、iの数ではありません。
重複した数字があるので、同時に、その最後に、重複した数字を取り除きます。
1つの#include <ビット/ STDC ++ H> 2 使用して 名前空間STDを、 3 typedefの長い 長いLL。 4 のconst int型 MAXN = 3E5 + 10 。 5 CONST LL MOD = 1E9 + 7 。 6 CONST LL INF = 1E18。 7 INTの DP [ 1050 ] [ 1010 ]。 8 INT メイン(){ 9 int型T。 10 のscanf(" %dの"、&T)。 11 しばらく(t-- ){ 12 のint D。 13の チャー S [ 15 ]。 14 INT VIS [ 15 ]。 15 INT [ 15 ]。 16 のscanf(" %sの%のD "、S&D) 17 INT LEN =のSTRLEN(S) 18 のmemset(DP、0、はsizeof (DP))。 19 のmemset(VIS、0、はsizeof (VIS))。 20 のために(INT I = 0; 私はLEN <; I ++ ) 21 [I] = sの[I] - ' 0 '、VIS [I]] ++ ; 22 DP [ 0 ] [ 0 ] = 1 。 23 のために(int型 I = 0 ; iが(< 1 << LEN)を、iが++ ){ 24 のために(INT J = 0 ; J <D; J ++ ){ 25 のための(int型のk = 0 ; <LEN kは、k個++ ){ 26 であれば((I&(1 << K))== 0) 27 DP [I | (1 << K)] [(J * 10 + [K])%のD] + = DP [I] [J]。 28 } 29 } 30 } 31 INT ANS = DP [(1 << LEN) - 1 ] [ 0 ]。 32 のために(int型 I = 0 ; iが= < 9 ; I ++ ) 33 のための(INT J = 1 ; J <= VIS [I]; J ++ ) 34 ANS / = J。 35 printf(" %d個の\ n " 、ANS)。 36 } 37 リターン 0 。 38 }