BZOJ 3131 [SDOI2013]淘金 - 数位DP
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的更多相关文章
- Bzoj 3131 [Sdoi2013]淘金 题解
3131: [Sdoi2013]淘金 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 733 Solved: 363[Submit][Status][ ...
- bzoj 3131 [Sdoi2013]淘金(数位DP+优先队列)
Description 小Z在玩一个叫做<淘金者>的游戏.游戏的世界是一个二维坐标.X轴.Y轴坐标范围均为1..N.初始的时候,所有的整数坐标点上均有一块金子,共N*N块. 一阵风吹 ...
- bzoj 3131 [Sdoi2013]淘金(数位dp)
题目描述 小Z在玩一个叫做<淘金者>的游戏.游戏的世界是一个二维坐标.X轴.Y轴坐标范围均为1..N.初始的时候,所有的整数坐标点上均有一块金子,共N*N块. 一阵风吹过,金子的位置发生了 ...
- [SDOI2013]淘金 数位DP
做了好久.... 大致思路: 求出前k大的方格之和即为答案, 先考虑一维的情况,设f[i]为数位上各个数相乘为i的数的总数,也就是对于数i,有f[i]个数它们各个位相乘为i, 再拓展到二维,根据乘法原 ...
- bozoj3131: [Sdoi2013]淘金 数位dp
链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3131 思路 1. 函数值的素因子只有2.3.5.7 由他们组成的状态不多,爆搜的时候即使搜不 ...
- bzoj 3131: [Sdoi2013]淘金
#include<cstdio> #include<iostream> #include<queue> #include<algorithm> #def ...
- BZOJ 3652: 大新闻(数位DP+概率论)
不得不说数位DP和博弈论根本不熟啊QAQ,首先这道题嘛~~~可以分成两个子问题: 有加密:直接算出0~n中二进制每一位为0或为1分别有多少个,然后分位累加求和就行了= = 无加密:分别算出0~n中二进 ...
- BZOJ 1833 数字计数 数位DP
题目链接 做的第一道数位DP题,听说是最基础的模板题,但还是花了好长时间才写出来..... 想深入了解下数位DP的请点这里 先设dp数组dp[i][j][k]表示数位是i,以j开头的数k出现的次数 有 ...
- BZOJ 4521 [CQOI2016]手机号码 - 数位DP
Description 在$[L, R]$找出有几个数满足两个条件 : 1 : 不同时含有$4$ 和 $8$ 2 : 至少有$3$个相邻的数相同 Solution 非常容易的数位DP, $pos$ 为 ...
随机推荐
- MongoDB应用场景
数据记录如下 /* 1 */ { "_id" : ObjectId("5b56dd19a171d7e9bfb03ac1"), "name" ...
- 我的第一篇博客之js的XXXX年XX月XX日 星期[日一-六] [上下]午 XX时:XX分
<!DOCTYPE html> <html> <head> <title>test</title> ...
- windows下配置pymysql
可以直接pip安装 pip install pyMysql
- bootstrap datatable
<table id="screenTable" data-toggle="table"> <thead> ... </thead& ...
- JDK8中JVM堆内存划分
一:JVM中内存 JVM中内存通常划分为两个部分,分别为堆内存与栈内存,栈内存主要用运行线程方法 存放本地暂时变量与线程中方法运行时候须要的引用对象地址. JVM全部的对象信息都 存放在堆内存中.相比 ...
- clearfix原理
[clearfix原理] .clearfix:after { <----在类名为“clearfix”的元素内最后面加入内容: content: "."; <----内容 ...
- Vi命令:如何删除全部内容
Vi命令:如何删除全部内容? 在命令模式下,输入:.,$d 一回车就全没了. 表示从当前行到末行全部删除掉. 用gg表示移动到首行.
- CSSの変数を使う
この文章はhttps://developer.mozilla.org/ja/docs/Web/CSS/Using_CSS_variablesを参考します. これは実験段階の機能です.この機能は複数のブ ...
- PHP使用UTF8编码读取ACCESS的乱码问题解决方案(转)
PHP使用UTF8编码读取ACCESS的乱码问题解决方案 http://it.xwstudy.com/readnews.php?id=627 来源:本站编辑 发布日期:2013-05-27 已有 17 ...
- Python complex() 函数
Python complex() 函数 Python 内置函数 描述 complex() 函数用于创建一个值为 real + imag * j 的复数或者转化一个字符串或数为复数.如果第一个参数为字 ...