zoukankan      html  css  js  c++  java
  • BZOJ 3131 [SDOI2013]淘金

    传送门

    Solution

    这道数位$DP$看的我很懵逼啊。。。

     

    首先我们肯定要先预处理出 $12$位乘起来的所有的可能情况, 记录入数组 $b$, 发现个数并不多, 仅$1e4$不到。

    然后我们考虑算出有多少的$x$ 使得$f(x) = y$, 并记录个数到$ans[y]$ 中。 

    然后? 然后我就不会啦QAQ

    定义数组$f[ i ][ j ][ k ]$ , $i$ 表示 $i$位数字, $j$ 表示 所有位上的数乘起来为 $b[j]$ , $k$ 表示前 $i$ 位是否比 $N$的前$i$位大。

    因为当$i = len$ 时, 是不允许比$N$大的, 所以$k$仅可能等于 $0 $

    然后就有转移方程 $f[ i  + 1][ nxt ][ (k  + x) > a[i + 1]]  += f[i][j][k]$

    算出$f$ 数组后, 相应地转移进 $ans[]$中, 最后进行排序,并用大根堆维护 、 取出

    Code

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<queue>
     5 #include<stdlib.h>
     6 using namespace std;
     7 typedef long long ll;
     8  
     9 const int N = 1e6;
    10 const ll mod = 1e9 + 7;
    11  
    12 int tot, len, a[20], k;
    13 ll b[N], f[20][40000][2], ans[N], n, maxn;
    14  
    15 struct node {
    16     int x, y;  ll val;
    17     node(int a, int b) {
    18         x = a; y = b;
    19         val = ans[a] * ans[b];
    20     }
    21     bool operator < (const node &b) const {
    22         return val < b.val;
    23     }
    24     bool operator > (const node &b) const {
    25         return val > b.val;
    26     }
    27 };
    28  
    29 priority_queue<node> q;
    30  
    31 ll fpow(ll a, ll b) {
    32     ll re = 1;
    33     for(; b; b >>= 1, a = a * a)
    34         if(b & 1) re = re * a;
    35     return re;
    36 }
    37  
    38 void dfs(int dep, ll sum, int rest) {
    39     b[++tot] = sum;
    40     if(dep > 9) return;
    41     if(!rest) return;
    42     for(int i = 0;  i <= rest; ++i) 
    43         dfs(dep + 1, sum * fpow(dep, i), rest - i); 
    44 }
    45  
    46 int fd(ll x) {
    47     return lower_bound(b + 1, b + 1 + tot, x) - b;
    48 }
    49  
    50 bool cmp(ll x, ll y) {
    51     return x > y;
    52 }
    53  
    54 int main()
    55 {
    56     scanf("%lld%d", &n, &k);
    57     while(n) {
    58         a[++len] = n % 10;
    59         n /= 10;
    60     }
    61     b[++tot] = 0;
    62     dfs(1, 1, len);
    63     sort(b + 1, b + 1 + tot);
    64     tot = unique(b + 1, b + 1 + tot) - b - 1;
    65     b[tot + 1] = 0x7fffffff;
    66     f[0][2][0] = 1;
    67 //  for(int i = tot; i >= tot - 10; --i)
    68 //      printf("%lld
    ", b[i]);
    69     for(int i = 0; i <= len; ++i)
    70         for(int j = 1; j <= tot; ++j)
    71             for(int k = 0; k < 2; ++k)
    72             if(f[i][j][k])
    73             for(int x = (i == 0)? 0 : 1; x < 10; ++x) {
    74                 int nxt = lower_bound(b + 1, b + 1 + tot, b[j] * x) - b;
    75                 f[i + 1][nxt][(k + x) > a[i + 1]] += f[i][j][k];
    76             }
    77     for(int i = 1; i <= tot; ++i) {
    78         for(int j = 1; j < len; ++j)
    79             ans[i] += f[j][i][0] + f[j][i][1];
    80         ans[i] += f[len][i][0];
    81     }
    82     sort(ans + 1, ans + 1 + tot, cmp);
    83 //  for(int i = 1; i <= 10; ++i)
    84 //      printf("%lld
    ", ans[i]);
    85     q.push(node(2, 2));
    86     while(!q.empty() && k) {
    87         node now = q.top(); q.pop();
    88         maxn = (maxn + now.val) % mod;
    89         if(!(--k)) break;
    90         if(now.x != now.y) {
    91             maxn = (maxn + now.val) % mod;
    92             if(!(--k)) break;
    93             q.push(node(now.x + 1, now.y));
    94         }
    95         if(now.x == 2) q.push(node(now.x, now.y + 1));
    96     }
    97     maxn = (maxn % mod + mod) % mod;
    98     printf("%lld
    ", maxn);
    99 }
    View Code
  • 相关阅读:
    Java线程面试题 Top 50
    深入理解java内存模型
    线程池的理解
    Thread的理解
    ThreadLocal的理解
    排序算法(简)
    排序算法
    【Java集合源码剖析】LinkedHashmap源码剖析
    vsftp上传文件权限问题
    xp 通过注册表修改环境变量
  • 原文地址:https://www.cnblogs.com/cychester/p/9642528.html
Copyright © 2011-2022 走看看