단단한 블럭인지를 확인하지 않고, 모든 경우를 구하면 되므로 다음과 같이 구할 수 있습니다.
해당 길이의 블럭의 수 ^ 블럭의 높이
col[m] = row[m] ^ n
이를 코드로 다음과 같이 나타낼 수 있습니다
Math.pow(x, y) 연산을 하게 되면 Overflow가 발생하므로 다음과 같이 곱셈 후 모듈러 연산을 해야합니다.
publicstaticintlegoBlocks(intn,intm){// ...(생략)// 레고 블럭을 쌓는 모든 경우의 수 저장하기long[]col=newlong[m+1];for(inti=0;i<=m;i++){col[i]=1;for(intj=1;j<=n;j++){col[i]*=row[i];// Overflow 방지를 위한 MOD 연산col[i]%=MOD;}}// ...(생략)}
단단하지 않은 블럭의 수 구하기는 앞에서 구했던 귀납적으로 블럭의 수 구하기와 유사합니다.
레고 블럭의 길이가 1 증가할 때마다 발생하는 경우의 수
위와 같이 j를 고정시켜두면, 나머지 길이(m - j)에서 어떻게 블럭을 쌓더라도 단단하지 않은 경우가 됩니다.
이 때, (m - j)에서 블럭을 쌓는 모든 경우의 수는 위에서 구한 값을 활용할 수 있습니다.
길이가 (m - j)인 단단하지 않은 블럭 : col[m - j]
이 때 j위치로 고정되어 있는 블럭의 왼쪽은 단단한 상태여야 하므로, 전체 경우의 수는 solid[j] * col[m - j]가 됩니다.4
이를 코드로 표현하면 다음과 같습니다.
publicstaticintlegoBlocks(intn,intm){// ...(생략)// Solid하지 않은 경우 빼서 Solid한 경우만 구하기long[]solidCol=newlong[m+1];solidCol[1]=1;// 길이가 1일 때는 크기가 1인 블럭을 쌓는 1가지 경우밖에 없음for(inti=2;i<=m;i++){longtemp=col[i];// 전체 경우의 수로 초기화for(intj=1;j<i;j++){// 길이를 1씩 증가시키면서 단단하지 않은 경우 빼기temp-=solidCol[j]*col[i-j];// Overflow 방지를 위한 MOD 연산temp%=MOD;}// Overflow 방지를 위한 MOD 연산2solidCol[i]=(temp+MOD)%MOD;// 연산 전 MOD를 더해서 계산 결과가 -인 경우 처리}// m번째 단단한 레고블럭 개수 출력return(int)solidCol[m];}
publicstaticintlegoBlocks(intn,intm){// Row 개수 구하기long[]row=newlong[m+1];for(inti=1;i<=m;i++){if(i<=4){row[i]=1;for(intj=1;j<i;j++)row[i]+=row[j];}else{row[i]=(row[i-1]+row[i-2]+row[i-3]+row[i-4])%MOD;}}// Row X Col 총 개수 구하기long[]col=newlong[m+1];for(inti=0;i<=m;i++){col[i]=1;for(intj=1;j<=n;j++){col[i]*=row[i];col[i]%=MOD;}}// Solid하지 않은 경우 빼서 Solid한 경우만 구하기long[]solidCol=newlong[m+1];solidCol[1]=1;for(inti=2;i<=m;i++){longtemp=col[i];for(intj=1;j<i;j++){temp-=solidCol[j]*col[i-j];temp%=MOD;}solidCol[i]=(temp+MOD)%MOD;}return(int)solidCol[m];}