[Luogu P3286] [BZOJ 3598] [SCOI 2014] 팡백의 백화점 여행
BZOJ 전송문
제목 설명
팡씨 아저씨는 어느 날 한 백화점에서 열리는 게임에 참가하러 갔다.상가에서 몇 명의 직원을 파견하여 한 줄로 늘어섰다.사람마다 앞에 돌무더기가 몇 무더기 있다.
공교롭게도 이 i i i 의 사람들 앞에 있는 제 j j 더미의 돌의 수량은 마침 이 i i가 K K K 진법으로 쓴 후 제 j j 위였다.지금 팡백은 게임을 하려고 하는데 백화점에서 팡백에게 정수 L, R L, R L, R 을 두 개 줄 것이다.
방백부는 위치를 [L, R] [L, R] [L, R] 중의 모든 사람의 돌을 합쳐서 돌무더기를 만들려고 한다.매번 조작할 때마다 그는 한 사람 앞에 있는 두 무더기의 돌을 선택하여 그 중의 한 무더기 중의 일부 돌을 다른 무더기로 옮길 수 있다. 그 대가는 이동하는 돌의 수량*이동의 거리이다.
백화점은 방 아저씨가 임무를 완수하기만 하면 야자를 주겠다고 약속했다. 대가가 적을수록 야자를 더 많이 주겠다.그래서 방 씨 아저씨는 매우 조급해서 당신이 그에게 가장 적은 대가가 얼마인지 알려주고 싶어 합니다.예를 들어 10 10 10진법 아래 12312 12312에 있는 사람이 돌을 합병하는 데 가장 적은 대가는 1 ∗ 2 + 2 ∗ 1 + 3 ∈ 0 + 1 ∈ 1 + 2 ∈ 2 = 9 1 * 2 + 2 * 2 * 1 + 3 * 0 + 1 * 1 + 2 * 2 * 2 * 2 = 9 1\872+2 + 2 + 2 = 9 1 ∈ 1 + 2 + 2 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 1 + 2 + 2 + 1 + 2 + 2 + 2 + 2 + 1 + 2 + 2 + 2 + 1 ͨ + 2 + 1 + 2 + 2 + 1 + 2 + 2 + 2 + 1
입력 출력 형식
입력 형식:
입력은 133개의 공백으로 구분된 정수 L, R, K L, R, K L, R, K L, R, K로 구성되어 있으며 백화점에서 방 아저씨에게 주는 222개의 정수와 진수를 나타냅니다.
출력 형식:
출력은 111줄에 불과하고 111개의 정수를 포함하여 최소한의 대가를 나타낸다.
출력 샘플 가져오기
샘플 #1 입력:
3 8 3
샘플 내보내기 #1:
5
설명
1 ≤ L ≤ R ≤ 1 0 15 , 2 ≤ K ≤ 20 1\le L\le R\le 10^{15}, 2\le K\le 20 1≤L≤R≤1015,2≤K≤20
문제 풀이 분석
ttcl, 이 문제를 오랫동안 생각했는데...
분명히 디지털 dp dp dp입니다.kk자릿수가 있는 PP에 대해 모든 자릿수의 숫자를 mmm위에 두면 공헌은 ∑i=1k∣i-m∣이다× d g t [ i ]\sum_{i=1}^{k}|i-m|\times dgt[i] ∑i=1k∣i−m∣×dgt[i].
그러면 우리는 먼저 모든 수를 마지막 자리에 놓고 한 자리씩 앞으로 옮길 수 있다.ii i에서 i-3 i-1 i-1 i-3 1위로 이동한 감소 기여는 상위 i-1 i-1 i-3 1위의 숫자와 차감된 K-3 i+1 K-i+1 K-3 i+1의 숫자와 차감된 K-3 i+1 K-i+1의 숫자다.이 값이 0보다 작으면 re t u r n return return으로 바로 이동하면 됩니다.
K≤20 K\le 20 K≤20이기 때문에 모든 수위와 크기가 크지 않습니다. 직접 dp[i][j]dp[i][j]dp[i][j]를 설정하면 앞의 ii자리 수와 jjj에 대한 기여의 합을 나타낼 수 있습니다.
코드는 다음과 같습니다.
#include
#include
#include
#include
#include
#include
#define R register
#define IN inline
#define W while
#define gc getchar()
#define ll long long
int num[70];
int K;
ll l, r;
ll dp[50][2050];
ll DFS(R int dgt, R int sum, R bool lim)
{
if (!dgt) return sum;
if ((!lim) && (~dp[dgt][sum])) return dp[dgt][sum];
int up = lim ? num[dgt] : K - 1;
ll ret = 0;
for (R int i = 0; i <= up; ++i)
ret += DFS(dgt - 1, sum + (dgt - 1) * i, lim & (i == up));
if (!lim) dp[dgt][sum] = ret;
return ret;
}
ll DFS(R int dgt, R int sum, R int pos, R bool lim)
{
if (sum < 0) return 0;
if (!dgt) return sum;
if ((!lim) && (~dp[dgt][sum])) return dp[dgt][sum];
int up = lim ? num[dgt] : K - 1;
ll ret = 0;
for (R int i = 0; i <= up; ++i)
if (dgt >= pos) ret += DFS(dgt - 1, sum + i, pos, lim & (i == up));
else ret += DFS(dgt - 1, sum - i, pos, lim & (i == up));
if (!lim) dp[dgt][sum] = ret;
return ret;
}
ll solve(R ll val)
{
int cnt = 0;
std::memset(dp, -1, sizeof(dp));
W (val) num[++cnt] = val % K, val /= K;
ll ret = DFS(cnt, 0, 1);
for (R int i = 2; i <= cnt; ++i)
std::memset(dp, -1, sizeof(dp)), ret -= DFS(cnt, 0, i, 1);
return ret;
}
int main(void)
{
scanf("%lld%lld%d", &l, &r, &K);
printf("%lld", solve(r) - solve(l - 1));
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
01 가방, 완전 가방, 다중 가방 dp(동적 기획 입문 dp)01 가방은 2진법으로 직접 표시할 수 있지만 데이터 양이 너무 많으면 시간을 초과하는 것이 폭력이다.01 가방의 사상은 바로 이 물품에 대해 내가 넣은 가치가 큰지 안 넣은 가치가 큰지 비교하여 방정식 f[i][v...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.