• 【SCOI2014】【BZOJ3598】方伯伯的商场之旅(数位dp)


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3598

    题意:

      对于一个数x,它含有一些小石子,每个石子的值为a[i](a[i]为x在k进制下的第i位),选一个石子的位置pos使得sum(a[i] * abs(i-pos))最小。 求出[L,R]中所有数这个值的和。

    题解:

      对于一个数,我们枚举最优位置时,可以发现从i->i+1的变化为+pre[i]-suf[i+1](分别为前缀和与后缀和)。

      30%的暴力分,我们枚举[L,R]中的数,然后进行上述操作即可。

      那么100%的分呢?我们考虑将每一个数的位置设为1,答案为a[i]*(i-1),然后数位dp求出初始花费cost。 对于将位置i->i+1的变化,+前i个数 -后i+1个数。我们考虑枚举这个操作,并且求出进行这一操作后对于这些数共计会优多少。

      上面那些看不懂的话来看这里吧_(:з」∠)_。

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <iostream>
     5 #define LL long long
     6 using namespace std;
     7 const int MaxN = 65;
     8 int u[MaxN], d[MaxN], LEN;
     9 LL l, r, k;
    10 LL f[MaxN][2][2], g[MaxN][1600], ans[2333], sum[MaxN][2][2];
    11 
    12 LL dp(int len, int up, int down){
    13     if (!len) { sum[len][up][down] = 1; return 0; }
    14     if (f[len][up][down]!= -1) return f[len][up][down];
    15     LL ret = 0ll, num = 0ll;
    16     int top = up ? u[len] : (int)k-1, bot = down ? d[len] : 0;
    17     for (int i = bot; i <= top; i++){
    18         int p1 = (i==top)&&up, p2 = i==bot&&down;
    19         ret += dp(len-1, p1, p2) + i*(len-1)*sum[len-1][p1][p2];
    20         num += sum[len-1][p1][p2];
    21     }
    22     f[len][up][down] = ret, sum[len][up][down] = num;
    23     return ret;
    24 }
    25 
    26 LL calc(LL x, LL y){
    27     int len = 0, len2 = 0;
    28     while(x){
    29         u[++len] = (int) (x%k);
    30         x /= k;
    31     }
    32     while(y){
    33         d[++len2] = (int) (y%k);
    34         y /= k;
    35     }
    36     LEN = len;
    37     return dp(len, 1, 1);
    38 }
    39 
    40 LL dfs(int len, int up, int down, int p, int s){
    41     if (!len) return (LL)s;
    42     if (!up && !down && g[len][s] != -1) return g[len][s];
    43     LL ret = 0;
    44     int top = up ? u[len] :(int)k-1, bot = down ? d[len] : 0;
    45     for (int i = bot; i <= top; i++){
    46         int x = (len >= p ? 1 : -1), c = i==top&&up, d = i==bot&&down;
    47         x = x*i + s;
    48         if (x < 0) break;
    49         ret += dfs(len-1, c, d, p, x);
    50     }
    51     if (!up && !down) g[len][s] = ret;
    52     return ret;
    53 }
    54 
    55 void Solve(){
    56     memset(f, -1ll, sizeof(f));
    57     LL ret = calc(r, l);
    58     //cout<<ret<<endl;
    59     LL dec = 0ll;
    60     for (int i = 2; i <= LEN; i++){
    61         memset(g, -1ll, sizeof(g)), dec += dfs(LEN, 1, 1, i, 0);
    62     }
    63     cout<<ret - dec;
    64 }
    65 
    66 int main(){
    67     cin>>l>>r>>k;
    68     Solve();
    69     return 0;
    70 }
    View Code
  • 相关阅读:
    scrum项目冲刺_day03总结
    scrum项目冲刺_day02总结
    关于Map的PUT的value值的问题
    oracle见表
    sql优化(转载)
    oracle注意事项
    mybatis中jdbcType的作用和是否必须
    spring 的web.xml的加载顺序
    spring 另开线程时的注入问题
    获取客户端的ip
  • 原文地址:https://www.cnblogs.com/Lukaluka/p/5206022.html
Copyright © 2020-2023  润新知