https://www.acmicpc.net/problem/20957
20957번: 농부 비니
타고난 농사꾼 비니는 최근 숫자 공부에 푹 빠졌다. 열심히 숫자 공부를 하던 비니는 놀라 자빠질 수밖에 없었다. 숫자 7이 비니가 가장 아끼는 낫과 비슷하게 생겼기 때문이다. 옛말에 낫 놓고 7
www.acmicpc.net
dp는 꾸준히 안하면 무조건 까먹을거 같다. 그중에서도 내가 젤 좋아하는 digit dp문제이다. digit dp를 좋아하는 이유는 직관적으로 규칙이 보이기 때문.
접근 방법
모든 숫자의 합과 곱을 알아야한다. digit dp는 n-1자리의 결과에서 0~9 숫자를 붙일 때 발생하는 규칙을 이용하여 dp 점화식을 세우면 쉽다. 내기준
- n-1 자리 모든 숫자의 합은 , 0~6의 모든 상태를 알아야한다. 어떤 숫자를 더해도 해당 숫자의 합을 기억해야한다.
- n-1 자리 모든 숫자의 곱은, 7의 배수인지 아닌지 2가지만 알면 된다.
- 7의 배수인 경우 어떤 숫자를 곱해도 7의배수이고,
- 7의 배수가 아닌 경우는 0, 7을 제외한 숫자를 곱하면 7의배수가 아니다.
그러므로 dp배열에 [자릿수], [각 자릿수의 합], [각 자릿수의 곱이 7인가] 를 저장하는 3차원 배열을 이용했다.
풀이
tag : dp
#include<iostream>
#define MOD int(1e9)+7
using namespace std;
int T,N;
int dp[10001][7][2]={0}; //n자리, 합mod7, 7배수인가
void solve(){
for(int i=2;i<=10000;i++){
for(int j=0;j<7;j++){
for(int k=0;k<=9;k++){ // 0 1 2 3 4 5 6 8 9
//곱이 7배수 아닌수 -> 곱이 7배수인수
if(k==7 || k==0){
dp[i][(j+k) % 7][1]+=dp[i-1][j][0];
dp[i][(j+k) % 7][1]%=MOD;
}
else {
//곱이 7배수 아닌수 -> 곱이7배수 아닌수
dp[i][(j+k) % 7][0]+=dp[i-1][j][0];
dp[i][(j+k) % 7][0]%=MOD;
}
//곱이 7배수인수 -> 그대로 곱이 7배수
dp[i][(j+k) % 7][1]+=dp[i-1][j][1];
dp[i][(j+k) % 7][1]%=MOD;
}
}
}
}
int main(){
cin>>T;
dp[1][0][1]=1; //7
dp[1][1][0]=2; //1 8
dp[1][2][0]=2; //2 9
dp[1][3][0]=1; //3
dp[1][4][0]=1; //4
dp[1][5][0]=1; //5
dp[1][6][0]=1; //6
solve();
while(T--){
cin>>N;
cout<<dp[N][0][1]<<endl;
}
}
숫자 0을 처리할 때 주의하자. 곱이 0인 경우도 7의 배수이다.
'Algorithm > BOJ' 카테고리의 다른 글
[백준/BOJ] 1536 개근상 - 접근과 풀이 (c++) (0) | 2022.09.30 |
---|---|
[백준/BOJ] 4991 로봇청소기 - 접근과 풀이 (c++) (0) | 2022.09.26 |
[백준/BOJ] 9019 DSLR - 접근과 풀이 (c++) (1) | 2022.09.16 |
[백준/BOJ] 2580 스도쿠 - 접근과 풀이 (c++) (0) | 2022.09.16 |
[백준/BOJ] 16946 벽 부수고 이동하기 4 - 접근과 풀이 (c++) (0) | 2022.09.14 |