Description

小Z在玩一个叫做《淘金者》的游戏。游戏的世界是一个二维坐标。X轴、Y轴坐标范围均为1..N。初始的时候,所有的整数坐标点上均有一块金子,共N*N块。
    一阵风吹过,金子的位置发生了一些变化。细心的小Z发现,初始在(i,j)坐标处的金子会变到(f(i),fIj))坐标处。其中f(x)表示x各位数字的乘积,例如f(99)=81,f(12)=2,f(10)=0。如果金子变化后的坐标不在1..N的范围内,我们认为这块金子已经被移出游戏。同时可以发现,对于变化之后的游戏局面,某些坐标上的金子数量可能不止一块,而另外一些坐标上可能已经没有金子。这次变化之后,游戏将不会再对金子的位置和数量进行改变,玩家可以开始进行采集工作。
    小Z很懒,打算只进行K次采集。每次采集可以得到某一个坐标上的所有金子,采集之后,该坐标上的金子数变为0。
    现在小Z希望知道,对于变化之后的游戏局面,在采集次数为K的前提下,最多可以采集到多少块金子?
    答案可能很大,小Z希望得到对1000000007(10^9+7)取模之后的答案。

Input

共一行,包含两介正整数N,K。

Output

一个整数,表示最多可以采集到的金子数量。

Sample Input

1 2 5

Sample Output

18

HINT

N < = 10^12 ,K < = 100000

对于100%的测试数据:K < = N^2

题解:

  开始想偏了……导致整个人都是懵逼的。

  首先打个表发现,各位数字乘积不同结果大概是8000左右,然后开始乱搞。

  设$f_{i,j,k}$表示总共i位,开头数字为j,乘积排名为k的总数,转移就比较显然。

  然后枚举每个k,接下来就是基本的数位DP了,这样我们求出了某一列上每个位置的金块数量$ans_{k}$,然后画个图发现,在$(i,j)$位置上的数量为我们刚才DP出的$ans_{i}*ans_{j}$,给$ans$排个序,然后贪心即可。

代码:

  

 #define Troy 10/11/2017

 #include <bits/stdc++.h>

 using namespace std;

 typedef long long ll;

 const ll mod=1e9+;

 inline ll read(){
ll s=,k=;char ch=getchar();
while(ch<''|ch>'') ch=='-'?k=-:,ch=getchar();
while(ch>&ch<='') s=s*+(ch^),ch=getchar();
return s*k;
} const int N=1e6; ll has[N];int num,p[],tot; inline void dfs(ll x,int from,int step){
if(step>) return ;
has[++num]=x;
for(;from<;from++){
dfs(x*from,from,step+);
}
} ll f[][][],n,k,ans[];//f[i][j][k]:i位开头为j乘积为k的答案 inline void init(){
has[++num]=;
dfs(,,);
sort(has+,has+num+);
num=unique(has+,has+num+)-has-;// printf("num=%d\n",num);
for(int i=;i<=;i++)
f[][i][lower_bound(has+,has+num+,i)-has]=;
for(int i=;i<=;i++){
for(int j=;j<;j++){
for(int k=;k<;k++)
for(int l=;l<=num;l++){
if(f[i-][k][l]==) continue;
int x;
if(has[l]*j<=has[num]){
x=lower_bound(has+,has+num+,has[l]*j)-has;
f[i][j][x]+=f[i-][k][l];
}
}
}
}
do{
p[++tot]=n%;
n/=;
}while(n);
} inline ll calc(int pos){
ll ret=;
for(int i=;i<tot;i++){
for(int j=;j<=;j++){
ret+=f[i][j][pos];
}
}
ll last=;
for(int i=tot;i;i--){
if(last>has[pos]||last==||has[pos]%last!=) break;
for(int j=;j<p[i];j++){
int x=lower_bound(has+,has++num,has[pos]/last)-has;
ret+=f[i][j][x];
}
last*=p[i];
}
return ret%mod;
} bool vis[][]; struct node {
int pos[];ll val;
friend bool operator <(node a,node b){
return a.val!=b.val?a.val<b.val:a.pos[]!=b.pos[]?a.pos[]>b.pos[]:a.pos[]>b.pos[];
}
}; priority_queue<node> q; int main(){
n=read(),k=read();
n++;
init();
for(int i=;i<=num;i++)
ans[i]=calc(i);
sort(ans+,ans+num+);
q.push((node){num,num,ans[num]*ans[num]});
ll ret=;
while(k&&(!q.empty())){
k--;
node now;
do{
now=q.top();q.pop();
}while(vis[now.pos[]][now.pos[]]&&(!q.empty()));
if(!vis[now.pos[]][now.pos[]]){
ret+=now.val;
ret%=mod;
if(now.pos[]>)
q.push((node){now.pos[]-,now.pos[],ans[now.pos[]-]*ans[now.pos[]]});
if(now.pos[]>)
q.push((node){now.pos[],now.pos[]-,ans[now.pos[]]*ans[now.pos[]-]});
}
vis[now.pos[]][now.pos[]]=true;
}
printf("%lld\n",ret);
}

【bzoj 3131】[Sdoi2013]淘金的更多相关文章

  1. Bzoj 3131 [Sdoi2013]淘金 题解

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

  2. bzoj 3131: [Sdoi2013]淘金

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

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

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

  4. BZOJ 3131 [SDOI2013]淘金 - 数位DP

    传送门 Solution 这道数位$DP$看的我很懵逼啊... 首先我们肯定要先预处理出 $12$位乘起来的所有的可能情况, 记录入数组 $b$, 发现个数并不多, 仅$1e4$不到. 然后我们考虑算 ...

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

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

  6. [Bzoj3131][Sdoi2013]淘金(数位dp)(优先队列)

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

  7. [BZOJ3131] [Sdoi2013]淘金

    [BZOJ3131] [Sdoi2013]淘金 Description 小Z在玩一个叫做<淘金者>的游戏.游戏的世界是一个二维坐标.X轴.Y轴坐标范围均为1..N.初始的时候,所有的整数坐 ...

  8. 题解-SDOI2013 淘金

    题面 SDOI2013 淘金 有一个 \(X\).\(Y\) 轴坐标范围为 \(1\sim n\) 的范围的方阵,每个点上有块黄金.一阵风来 \((x,y)\) 上的黄金到了 \((f(x),f(y) ...

  9. bzoj千题计划268:bzoj3131: [Sdoi2013]淘金

    http://www.lydsy.com/JudgeOnline/problem.php?id=3131 如果已知 s[i]=j 表示有j个<=n数的数码乘积=i 那么就会有 s[a1]*s[a ...

随机推荐

  1. centos 7下安装python 3.6笔记

    每次在centos上安装python 3都需要重新查资料,这次索性自己记下笔记. 首先安装gcc yum -y install gccyum install zlib-devel./configure ...

  2. Python 3 中的json模块使用

    1. 概述 JSON (JavaScript Object Notation)是一种使用广泛的轻量数据格式. Python标准库中的json模块提供了JSON数据的处理功能. Python中一种非常常 ...

  3. 在 javascript 中,为什么 [1,2] + [3,4] 不等于 [1,2,3,4]?

    在 stackoverflow 上有人提问:arrays - Why does [1,2] + [3,4] = "1,23,4" in JavaScript? 问题 我想将一个数组 ...

  4. happens-before规则和指令重排

                                                                                                         ...

  5. JQuery DOM操作 、属性和CSS样式操作、其他函数

    DOM操作 1.在div1内部最后追加一个节点 $("#div1").append("<img src='../01-HTML基本标签/img/Male.gif'/ ...

  6. Django升级1.8的一些问题

    1.最明显的问题当然是Settings设置中关于模板的设置数据结构发生变化,这个就不细说了,你开个Django的1.8的新项目就知道怎么改了 2.migrations问题,这个问题是1.8最主要的修改 ...

  7. .gitignore文件不起作用的解决方法

    http://keendawn.blog.163.com/blog/static/88880743201531554431124/ git rm -r --cached . git add . git ...

  8. pc端页面打包成安卓apk

    一.phoneGap PhoneGap是一个采用HTML,CSS和JavaScript的技术,创建移动跨平台移动应用程序的快速开发平台.它使开发者能够在网页中调用IOS,Android,Palm,Sy ...

  9. 分布式任务调度平台XXL-JOB

    <分布式任务调度平台XXL-JOB>       一.简介 1.1 概述 XXL-JOB是一个轻量级分布式任务调度框架,其核心设计目标是开发迅速.学习简单.轻量级.易扩展.现已开放源代码并 ...

  10. 智能指针auto_ptr & shared_ptr

    转载:智能指针auto_ptr 很多人听说过标准auto_ptr智能指针机制,但并不是每个人都天天使用它.这真是个遗憾,因为auto_ptr优雅地解决了C++设计和编码中常见的问题,正确地使用它可以生 ...