• 【bzoj3598】: [Scoi2014]方伯伯的商场之旅


    Description

    方伯伯有一天去参加一个商场举办的游戏。商场派了一些工作人员排成一行。每个人面前有几堆石子。说来也巧,位置在 i 的人面前的第 j 堆的石子的数量,刚好是 i 写成 K 进制后的第 j 位。
    现在方伯伯要玩一个游戏,商场会给方伯伯两个整数 L,R。方伯伯要把位置在 [L, R] 中的每个人的石子都合并成一堆石子。每次操作,他可以选择一个人面前的两堆石子,将其中的一堆中的某些石子移动到另一堆,代价是移动的石子数量 * 移动的距离。商场承诺,方伯伯只要完成任务,就给他一些椰子,代价越小,给他的椰子越多。所以方伯伯很着急,想请你告诉他最少的代价是多少。
    例如:10 进制下的位置在 12312 的人,合并石子的最少代价为:
    1 * 2 + 2 * 1 + 3 * 0 + 1 * 1 + 2 * 2 = 9
    即把所有的石子都合并在第三堆

    Input

    输入仅有 1 行,包含 3 个用空格分隔的整数 L,R,K,表示商场给方伯伯的 2 个整数,以及进制数

    Output

     输出仅有 1 行,包含 1 个整数,表示最少的代价。

    Sample Input

    3 8 3

    Sample Output

    5

    HINT

     1 < =  L < =  R < =  10^15, 2 < =  K < =  20

    题解:

      据说是数位DP水题,EXM?

      一开始想了个5维DP……想了想不太对,怂了题解……

      先强制性让集合点为最低位,然后得到一个答案,但显然这个不是最优解,那么考虑当某个数集合点从低位转移到高一位的要求,即此位以前数字之和要大于后面数之和,若用$a_{i}(P)$表示P进制下第i位的数字,这个条件就是:$sum_{x=i+1}^n a_{x}(P)>=sum_{x=1}^{i-1}a_{x}(P)$。在考虑如何DP。

      首先对于强制性选择最低位,可以直接数位DP,这部分很裸;接着,考虑从次低位到最高位为集合点的减少量,记忆化搜索的时候我们传一个选取位置,当当前位数大于等于此值时我们加上此位枚举值,反之减去,若减去到某位后和小于了0,那么说明这个状态不满足进位集合,直接返回0即可。最后我们用第一次DP出的答案减去之后枚举新集合点的减少量即为答案。

      (话说第一次打记忆化搜索,感觉怪怪的。)

    代码(抄来的233):

       

     1 #define Troy 10/11/2017
     2 
     3 #include <bits/stdc++.h>
     4 
     5 using namespace std;
     6 
     7 typedef long long ll;
     8 
     9 ll f[100][9*20*20],P;
    10 
    11 int num,p[100];
    12 
    13 inline ll dfs(int pos,int sum,bool limit){
    14     if(pos==0)  return sum;
    15     if(!limit&&f[pos][sum]!=-1) return f[pos][sum];
    16     int end=limit?p[pos]:P-1;
    17     ll ret=0;
    18     for(int i=0;i<=end;i++)
    19         ret+=dfs(pos-1,sum+(pos-1)*i,limit&&i==end);
    20     if(!limit)  f[pos][sum]=ret;
    21     return ret;
    22 }
    23 
    24 inline ll dfs(int pos,int up,int sum,bool limit){
    25     if(sum<0)   return 0;
    26     if(pos==0)  return sum;
    27     if(!limit&&f[pos][sum]!=-1) return f[pos][sum];
    28     int end=limit?p[pos]:P-1;
    29     ll ret=0;
    30     for(int i=0;i<=end;i++)
    31         if(pos>=up) ret+=dfs(pos-1,up,sum+i,limit&&i==end);
    32         else    ret+=dfs(pos-1,up,sum-i,limit&&i==end);
    33     return  limit==0?f[pos][sum]=ret:ret;
    34 }
    35 
    36 inline ll calc(ll n){
    37     num=0;
    38     do{ 
    39         p[++num]=n%P;
    40         n/=P;
    41     }while(n);
    42     memset(f,-1,sizeof(f));
    43     ll ret=dfs(num,0,true);
    44     for(int i=2;i<=num;i++)
    45         memset(f,-1,sizeof(f)),ret-=dfs(num,i,0,true);
    46     return ret;
    47 }
    48 
    49 int main(){
    50     ll a,b;
    51     scanf("%lld%lld%lld",&a,&b,&P);
    52     printf("%lld
    ",calc(b)-calc(a-1));
    53 }   
  • 相关阅读:
    HBase 高性能加入数据
    Please do not register multiple Pages in undefined.js 小程序报错的几种解决方案
    小程序跳转时传多个参数及获取
    vue项目 调用百度地图 BMap is not defined
    vue生命周期小笔记
    解决小程序背景图片在真机上不能查看的问题
    vue项目 菜单侧边栏随着右侧内容盒子的高度实时变化
    vue项目 一行js代码搞定点击图片放大缩小
    微信小程序进行地图导航使用地图功能
    小程序报错Do not have xx handler in current page的解决方法
  • 原文地址:https://www.cnblogs.com/Troywar/p/7652774.html
Copyright © 2020-2023  润新知