传送门

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

 #include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<stdlib.h>
using namespace std;
typedef long long ll; const int N = 1e6;
const ll mod = 1e9 + ; int tot, len, a[], k;
ll b[N], f[][][], ans[N], n, maxn; struct node {
int x, y; ll val;
node(int a, int b) {
x = a; y = b;
val = ans[a] * ans[b];
}
bool operator < (const node &b) const {
return val < b.val;
}
bool operator > (const node &b) const {
return val > b.val;
}
}; priority_queue<node> q; ll fpow(ll a, ll b) {
ll re = ;
for(; b; b >>= , a = a * a)
if(b & ) re = re * a;
return re;
} void dfs(int dep, ll sum, int rest) {
b[++tot] = sum;
if(dep > ) return;
if(!rest) return;
for(int i = ; i <= rest; ++i)
dfs(dep + , sum * fpow(dep, i), rest - i);
} int fd(ll x) {
return lower_bound(b + , b + + tot, x) - b;
} bool cmp(ll x, ll y) {
return x > y;
} int main()
{
scanf("%lld%d", &n, &k);
while(n) {
a[++len] = n % ;
n /= ;
}
b[++tot] = ;
dfs(, , len);
sort(b + , b + + tot);
tot = unique(b + , b + + tot) - b - ;
b[tot + ] = 0x7fffffff;
f[][][] = ;
// for(int i = tot; i >= tot - 10; --i)
// printf("%lld\n", b[i]);
for(int i = ; i <= len; ++i)
for(int j = ; j <= tot; ++j)
for(int k = ; k < ; ++k)
if(f[i][j][k])
for(int x = (i == )? : ; x < ; ++x) {
int nxt = lower_bound(b + , b + + tot, b[j] * x) - b;
f[i + ][nxt][(k + x) > a[i + ]] += f[i][j][k];
}
for(int i = ; i <= tot; ++i) {
for(int j = ; j < len; ++j)
ans[i] += f[j][i][] + f[j][i][];
ans[i] += f[len][i][];
}
sort(ans + , ans + + tot, cmp);
// for(int i = 1; i <= 10; ++i)
// printf("%lld\n", ans[i]);
q.push(node(, ));
while(!q.empty() && k) {
node now = q.top(); q.pop();
maxn = (maxn + now.val) % mod;
if(!(--k)) break;
if(now.x != now.y) {
maxn = (maxn + now.val) % mod;
if(!(--k)) break;
q.push(node(now.x + , now.y));
}
if(now.x == ) q.push(node(now.x, now.y + ));
}
maxn = (maxn % mod + mod) % mod;
printf("%lld\n", maxn);
}

BZOJ 3131 [SDOI2013]淘金 - 数位DP的更多相关文章

  1. Bzoj 3131 [Sdoi2013]淘金 题解

    3131: [Sdoi2013]淘金 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 733  Solved: 363[Submit][Status][ ...

  2. bzoj 3131 [Sdoi2013]淘金(数位DP+优先队列)

    Description 小Z在玩一个叫做<淘金者>的游戏.游戏的世界是一个二维坐标.X轴.Y轴坐标范围均为1..N.初始的时候,所有的整数坐标点上均有一块金子,共N*N块.    一阵风吹 ...

  3. bzoj 3131 [Sdoi2013]淘金(数位dp)

    题目描述 小Z在玩一个叫做<淘金者>的游戏.游戏的世界是一个二维坐标.X轴.Y轴坐标范围均为1..N.初始的时候,所有的整数坐标点上均有一块金子,共N*N块. 一阵风吹过,金子的位置发生了 ...

  4. [SDOI2013]淘金 数位DP

    做了好久.... 大致思路: 求出前k大的方格之和即为答案, 先考虑一维的情况,设f[i]为数位上各个数相乘为i的数的总数,也就是对于数i,有f[i]个数它们各个位相乘为i, 再拓展到二维,根据乘法原 ...

  5. bozoj3131: [Sdoi2013]淘金 数位dp

    链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3131 思路 1. 函数值的素因子只有2.3.5.7 由他们组成的状态不多,爆搜的时候即使搜不 ...

  6. bzoj 3131: [Sdoi2013]淘金

    #include<cstdio> #include<iostream> #include<queue> #include<algorithm> #def ...

  7. BZOJ 3652: 大新闻(数位DP+概率论)

    不得不说数位DP和博弈论根本不熟啊QAQ,首先这道题嘛~~~可以分成两个子问题: 有加密:直接算出0~n中二进制每一位为0或为1分别有多少个,然后分位累加求和就行了= = 无加密:分别算出0~n中二进 ...

  8. BZOJ 1833 数字计数 数位DP

    题目链接 做的第一道数位DP题,听说是最基础的模板题,但还是花了好长时间才写出来..... 想深入了解下数位DP的请点这里 先设dp数组dp[i][j][k]表示数位是i,以j开头的数k出现的次数 有 ...

  9. BZOJ 4521 [CQOI2016]手机号码 - 数位DP

    Description 在$[L, R]$找出有几个数满足两个条件 : 1 : 不同时含有$4$ 和 $8$ 2 : 至少有$3$个相邻的数相同 Solution 非常容易的数位DP, $pos$ 为 ...

随机推荐

  1. CSS 颜色

    color属性可以指定HTML文本的颜色. HTML的颜色采用以下3种方式表示. RGB值 使用红色.绿色.蓝色等不同比例表示,如 1 rgb(100,90,90) 值在0~255之间. 十六进制编码 ...

  2. 运用active和hover实现导航栏的页面切换

    .nav ul li a:hover{ background: #3E6EDD;}.nav ul li a:hover img{ display: block;}.nav ul li a.active ...

  3. python list [:1]

    python 切片slice 1.补充: A = np.ones([, , ]) B = np.ones([, ]) C = A*B[:, None, :] C.shape = 2,1,4 https ...

  4. Error:svn: E160013 svn主干切换分支时报错

    Error:svn: E160013: û���ҵ��ļ�: �汾��10574����·�� ��/aap/branches/20180613�� 前几天遇到了这个问题,心里特别崩溃,之前可以从主干 ...

  5. js实现多级复选框的交互

    功能介绍   整个复选框是包含多级,可能有父级,可能有子级,在勾选复选框时,要做两种判断: 1要判断它下面有没有子级,有子级将子级的选中状态checked变得和自己一样. 2要判断它是否有父级,有父级 ...

  6. vmware 完全关闭时间同步

    参考 http://blog.51cto.com/hezhang/1535577 修改.vmx文件 tools.syncTime = "FALSE" time.synchroniz ...

  7. Android笔记:ContextMenu

    ContextMenu,称为上下文菜单,也就是长按界面不放,弹出的菜单.使用ContextMenu有三个步骤: (1)调用registerForContextMenu()方法,为视图注册上下文菜单: ...

  8. es快照定时备份脚本

    #!/bin/bashdata1=`date "+%Y%m%d"`data2="http://0.0.0.0:9200/_snapshot/my_backup/snaps ...

  9. 将秒数转为HH:MM:SS格式的时间

    /**  * 将秒数转为HH:MM:SS格式的时间  * @param $seconds  * @return string  */ public static function GetHHMMSSB ...

  10. pta l2-13(红色警报)

    题目链接:https://pintia.cn/problem-sets/994805046380707840/problems/994805063963230208 题意:给n个顶点,m条边,问每次删 ...