다이 시뮬레이터 각 롤 1~6에서 난수를 생성한다. 당신은 수 롤백 할 수 없습니다 있도록 발전기에 제약을 도입 i
보다 rollMax[i]
(1 인덱스) 번 연속.
정수 배열을 감안 rollMax
하고 정수 n
, 정확하게 얻을 수있다 고유 시퀀스의 수 복귀 n
롤.
적어도 하나 개의 원소가 서로 다르면 두 시퀀스는 상이한 것으로 간주된다. 대답은 너무 큰 수 있기 때문에, 그것을 모듈을 반환합니다 10^9 + 7
.
예 1 :
입력 : N = 2 ROLLMAX = [1,1,2,2,2,3] 출력 : 34 명 : 다이에 아무런 제약이없는 경우가 있으며, 다이 롤 (2)이있을 것이다 6 * 6 = 36 가능한 조합. 이 경우, ROLLMAX 어레이를 찾고, 숫자 1과 2는 따라서 순서 (1,1) 및 (2,2)가 발생할 수없는 최대 회 연속적으로 표시되므로, 최종 응답은 36-2 = 34이다.
예 2 :
입력 : N = 2 ROLLMAX = [1,1,1,1,1,1] 출력 : 30
예 3 :
입력 : N = 3 ROLLMAX = [1,1,1,2,2,3] 출력 : 181
제약 :
1 <= n <= 5000
rollMax.length == 6
1 <= rollMax[i] <= 15
동적 프로그래밍 솔루션 (1)
주 정의 : DP [I] [J] : 상기 마지막 번호 인 I와 J 롤의 다른 시퀀스의 총 수. 초기화 : J에 대한 DP [1] [J] = 1, [0, 5]. (0 인덱스에 매핑 1 인덱스). 답 : DP [N]의 합에 대한 J [J] [0, 5].
상태 전이 분석 : DP [I] [J]의 두 가지 경우가있을 수있다 : 하나의 마지막 압연 번호는 이전 번호가 상이한 또는 이전과 동일하다.
첫 번째 경우에있어서, 단순히 0 내지 5 J를 반복하고 모든 DP 추가 [I - 1 [K]는 K = J가 [I] [J]를 DP 어디!.
두 번째 경우, 우리는 일본의 두 개의 연속 압연 번호가 이미 있다는 것을 알고있다. 우리는 대부분의 ROLLMAX [J] 연속 J에서 할 수 있습니다. ROLLMAX [j]가 15 이하인 때문에, 우리는 2, 3, 4 ... ROLLMAX [J] 연속 J 끝나는 모든 서열을 추가 할 수있다.
그렇게에서 몇 가지 핵심 포인트 :
J의 고정 된 연속 번호 1, 우리는 모든 DP를 추가 할 필요가, CNT 말 [I - CNT] [t] 여기서 t = J!. 이는 탄소 나노 튜브의 정확한 연속 J로 끝나는 모든 시퀀스를 나타냅니다.
2. 합계를 종료 두 가지 시나리오가있다. 어느 우리 ROLLMAX [J]의 한계를 초과하거나 우리 롤의 부족, 즉, 롤의 현재 수는 <= ROLLMAX [J]이다. ROLLMAX [J]를 초과하는 경우, 단순히 중지; 우리가 롤 아웃 인 경우, 우리는 난 경우 모두 롤 전체 JS를 계산 DP에 [I] [J]를 1을 추가 할 필요가있다. 우리가 공 롤이있을 때, 우리가 선택할 수있는 J와 다른 다른 5 개 개의 번호를 가지고 있지 않기 때문입니다. 그것은 단지 그것에서 J를 가지고 한 순서입니다.
런타임은 O이다 (N * 6 * 15 * 6). 공간 복잡도는 O이다 (N * 6).
실수했다 : 최종 결과 입술을 합산하면 입술을 사용 = (DP 입술 + [N] [I]) 개조 %; 입술 + DP = [N] [i]를 개조 %; 이 업데이트 된 입술의 모듈러 연산을 적용하지 않기 때문에 올바르지 만 각 DP [n]은 [I]에 %를 적용한다.
클래스 해결 { 공개 INT dieSimulator ( INT의 n은, 값 int [] ROLLMAX) { INT 개조 = ( INT ) + 1E9 (7) ; 긴 DP [] [] = 새로운 긴 [N + 1] [6 ] 긴 입술 = 0 ; Arrays.fill (DP [ 1], 1 ); 위한 ( int로 I = 2; 나는 = <N; i가 ++ ) { 대 ( INT의 J = 0; J <6; J ++ ) { 대 ( INT에서 K = 0; K <6; 케이 ++) { 경우 (j =! K) { DP [I] [J] = (DP [I] [J] + DP [내가 - 1 [K]) %의 모드; } 다른 { INT의 CNT = 2 ; 대 (; CNT <= ROLLMAX [J] && CNT <I; CNT ++ ) { 대 ( INT의 t = 0; t <6; t ++ ) { 경우 (t에서의 == J)가 { 계속 ; } DP [I] [J]= (DP [I] [J] + DP [I - CNT] [t]) %의 모드; } } 경우 (CNT <= ROLLMAX [J] && CNT == I) { DP [I] [J] = (DP [I] [J] + 1) % 개조; } } } } } 에 대해 ( int로 ; I <6, I = 0 난 ++ ) { 입술 = (DP 입술 + [N] [I]) % 개조; } 리턴 ( INT ) 입술을; } }
동적 프로그래밍 용액 2.
주 : 차원 배열을 선언 DP [2] [6] [16]. 제 1 회 차원은 우리가 하나 더 주사위 롤의 현재 반복을 calcuate하기 위해 이전의 연산 결과를 사용하는 것처럼 롤링 인덱스입니다. 제 2 치수는 지난 압연 수를 나타내며 3 dimenstion은 지난 압연 수의 연속적인 시간을 나타냅니다. 여기에 3 차원은 0 ~ 15 포함에서입니다. 0 전류 수가 최종 압연 수 없다 따라서는 연속적인 시간이 0 있도록 마지막 롤, 다른 번호를 얻을 수 있음을 의미한다.
우리가 하나 더 주사위 롤을 때마다, 우리는 모든 가능한 시퀀스 카운트의 현재 상태를 나타내는 새로운 2D 배열을 계산한다. 그래서 외부 루프는 n으로 2에서 이동합니다. 우리는 다음과 같이 내부 :
1. 계산 될 새로운 2D 어레이를 초기화.
1 이상의 롤 숫자 t를 생성하는 경우 연속 시간 J의 난 각 번호 2, 즉 난 DP [(K + 1) % 2] [t] [1] + = DP [K % 2] [아니다 I] [J] 만약 t == 난 후 우리 ROLLMAX [t], DP의 한도를 초과하지 않은 경우 [(케이 + 1) % 2] [t] [J + 1] + = DP [K % 2] [t] [제이].
초기화 : 1 롤, 회 연속 1의 각 번호 1 개 순서가있다.
답변 : 모든 순서는 J의 0 ~ 15 회 연속으로 1에서 6까지 숫자 J에서 끝나야합니다. 그래서 최종 답변은 마지막으로 계산 된 2 차원 배열의 단지 합계입니다.
클래스 해결 { 공개 INT dieSimulator ( INT의 n은, 값 int [] ROLLMAX) { INT 개조 = ( INT ) + 1E9 (7) ; 긴 입술 = 0 ; 긴 [] [] [] DP = 새로운 긴 [2] [6] [16 ]; // INIT : 연속 1 시간 압연 번호 1 롤 위해 ( int로 ; I <6, I = 0 난 ++ ) { DP [ 0] [i]는 [1] = 1 ; } // DP [(K + 1) % 2] [I] [J] DP보다 1 이상의 롤을 갖는다 K % 2] [I] [J] 대 (INT의 K = 2; K <= N; K ++ ) { // 재 초기화 DP [(K + 1) % 2]를 계산하기 전에 대한 ( INT를 p = 0; p <6; P ++ ) { Arrays.fill (DP [(K + 1) % 2] P, 0 ); } 에 대해 ( int로 내가 6 <; I = 0 난 ++ ) { 위해 ( INT의 J = 0; J ++ <= 15 J ) { // 1 이상의 롤이 어떤 숫자가 될 수 대 ( INT의 t = 0; t <6 ; t ++ ) { 경우 ! (t = I) { DP [(K+ 1) % 2] [t] [1] = (DP [(K + 1) % 2] [t] [1] + DP [% K 2] [I] [J]) % 개조; } 다른 경우 (j + 1 <= ROLLMAX [t]) { DP [(K + 1) % 2] [t] [J + 1] = (DP [(K + 1) % 2] [t] [J + 1] + DP [% K 2] [t] [J]) %를 개조하는 단계; } } } } } // 합까지의 모든 시퀀스 길이 [] [] resDp DP = [(N + 1) % 2 ]; 위한 ( int로 ; I <6, I = 0 난 ++ ) { 위해 ( INT의 ) {J = 0; J <= 15; j 개의 ++의 입술 = (입술 resDp + [I] [J]) %의 모드; } } 리턴 ( INT ) 입술을; } }