BZOJ1026 [SCOI2009] windy 수(디지털 dp)
[문제풀이]
먼저 수조 dp, f:dp[i][j]를 미리 처리하면 다음과 같다. i위에서 j를 채우는 windy수는 몇 개(개수는 1위, 10위는 2위...)
상태 이동: 맨 왼쪽에 한 개씩 입력:
dp[i][j]=sigma(dp[i-1][k]), 0<=k<=9 및 abs(j-k)>=2
경계: dp[1][j]=1
A에서 B까지 계수할 때 A와 B의 위치가 같지 않으면 가장 높은 위치는 0이 될 수 있다. f[i]로 i위를 가장 높은 위치로 기록하고 가장 높은 위치는 0의 windy 수를 기록한다.
그럼, f[i]=f[i-1]+sigma(dp[i-1][j]), 1<=j<=9
개수:
1. 다음에도 상계가 있고 귀찮아서 접두사와 사상을 활용할 수 있다
2. 높은 위치에서 낮은 위치까지 0~x에서 windy의 개수를 통계한다. x의 i위 수를 num[i]로 설정하고 윗자리에서num[i+1]를 채울 때(최고위 특수처리):
우선, 이 분은 0~num[i]-1, 뒤에 마음대로 채울 수 있습니다. ans+=sigma(dp[i-1][j]), i가 가장 높은 자리가 아니라면 윗사람과의 차이에 주의해야 합니다>=2
그리고 이분은num[i],ans가 다음 분과 관련되어 다음 분을 처리할 수 있습니다.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
typedef long long LL;
LL dp[20][20]={0},f[20]={0};
void init()
{
int i,j,k;
f[1]=1;
for(i=0;i<=9;i++)
dp[1][i]=1;
for(i=2;i<=10;i++)
{
for(j=0;j<=9;j++)
for(k=0;k<=9;k++)
if(abs(j-k)>=2) dp[i][j]+=dp[i-1][k];
f[i]=f[i-1];
for(j=1;j<=9;j++)
f[i]+=dp[i-1][j];
}
}
LL solve(int x)// 0~x-1 windy
{
int num[20]={0};
LL ans=0;
int p=0,i,j;
while(x!=0)
{
num[++p]=x%10;
x/=10;
}
ans=f[p];// 0
for(i=1;i<num[p];i++)// 1~num[p]-1
ans+=dp[p][i];
for(i=p-1;i>=1;i--)// num[p],
{
for(j=0;j<num[i];j++)
if(abs(num[i+1]-j)>=2) ans+=dp[i][j];
if(abs(num[i+1]-num[i])<2) break;
}
return ans;
}
int main()
{
int A,B;
scanf("%d%d",&A,&B);
init();
printf("%lld",solve(B+1)-solve(A));//
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Gym 100623J Just To Lucky(디지털 dp)제목: 1-n 중 몇 개의 숫자가 그 자체를 만족시키고 각 수위에 의해 정제될 수 있는지; 사고방식: n은 10의 12차원이다. 곧 디지털 dp라고 생각할 수 있다. 그때는 판자가 없어서 디지털 dp를 어떻게 두드렸...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.