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

/*
数位DP+堆
这个题比较显然的做法是求出一维的转移,然后再用堆求出二维的前K大,问题是数据太大,无法直接求一维的。
我们可以发现,最大的积在10000左右,所以可以先dfs出所有可能的积,然后用数位DP求出积的个数。
f[i][j][k]表示填了i为,积为j,下一维能否任意填数的方案数。
*/
#include<cstdio>
#include<algorithm>
#include<iostream>
#include<queue>
#define mod 1000000007
#define lon long long
#define N 400010
using namespace std;
lon n,k,a[N],len,dis[N],cnt,size[N],num[N],f[][N][];
struct node{
lon x,y,val;
node(lon a,lon b){x=a;y=b;val=size[num[a]]*size[num[b]];}
bool operator<(node s1) const{
return val<s1.val;
}
};priority_queue<node> q;
lon read(){
lon num=,flag=;char c=getchar();
while(c<''||c>''){if(c=='-')flag=-;c=getchar();}
while(c>=''&&c<=''){num=num*+c-'';c=getchar();}
return num*flag;
}
bool cmp(int a,int b){return size[a]>size[b];}
void dfs(lon last,lon dep,lon now){
if(dep==len+){
dis[++cnt]=now;
return;
}
if(!now) return;
for(lon i=last;i<;i++)
dfs(i,dep+,now*i);
}
int main(){
n=read();k=read();
while(n){
a[++len]=n%;
n/=;
}
dfs(,,);
dis[++cnt]=;
sort(dis+,dis+cnt+);
cnt=unique(dis+,dis+cnt+)-dis-;
f[][][]=;
for(lon i=;i<=len;i++)
for(lon j=;j<=cnt;j++)
for(lon l=;l<;l++)
if(f[i][j][l]){
lon p=(i==?:);
for(;p<;p++){
f[i+][lower_bound(dis+,dis+cnt+,dis[j]*p)-dis][l+p>a[i+]]+=f[i][j][l];
}
}
for(lon i=;i<=cnt;i++){
num[i]=i;
for(lon j=;j<len;j++)
size[i]+=f[j][i][]+f[j][i][];
size[i]+=f[len][i][];
}
sort(num+,num+cnt+,cmp);
q.push(node(,));
lon i=,ans=;
while(!q.empty()){
node temp=q.top();
q.pop();
ans=(ans+temp.val)%mod;
i++;
if(i>=k) break;
if(temp.x!=temp.y){
ans=(ans+temp.val)%mod;
i++;
if(i>=k) break;
}
if(temp.x!=temp.y) q.push(node(temp.x+,temp.y));
if(temp.x==) q.push(node(temp.x,temp.y+));
}
cout<<ans;
return ;
}

淘金(bzoj 3131)的更多相关文章

  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]淘金

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

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

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

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

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

  7. SDOI2013 R1 Day2

    目录 2018.3.25 Test 总结 T1 BZOJ.3129.[SDOI2013]方程(扩展Lucas 容斥) T2 洛谷.3305.[SDOI2013]费用流(最大流ISAP 二分) T3 B ...

  8. My_Plan part1 小结

    数位DP AC十道题目以上 成就达成 八月份!三个月!想想就令人兴奋呢 开始写总结啦 貌似简单的数位DP只需要改改模板就可以啦 就按照我的做题顺序开始总结吧 先是学习了一发模板:http://www. ...

  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. UVA - 1279 Asteroid Rangers (动点的最小生成树)

    题意,有n个匀速动点,求最小生成树的改变次数. 一句话总结:动态问题的一般做法是先求出一个静态的解,然后求出解发生改变的事件,事件按照时间排序,依次处理. 先求出最开始的最小生成树(MST),当MST ...

  2. C-基础:atoi

    C语言库函数名: atoi 功 能: 把字符串转换成整型数. 名字来源:ASCII to integer 的缩写. 原型: int atoi(const char *nptr); 函数说明: 参数np ...

  3. request :fail url not in domain list

    1.可点击开发者工具右上角 详情-域名信息,看看是否配置了域名: 2. 手机预览小程序的时候,打开调试

  4. thinkphp网站后门-发现后门(Webshell)文件

    不知道能不能解决, 1.登录阿里云后台,找到后门文件删除 2.执行 中国镜像 composer config -g repo.packagist composer https://packagist. ...

  5. jpeg和jpg的区别是什么

    JPG是JPEG的简写,jpg是后缀名,jpeg既可作为后缀名,又能代表文件格式:JPG——JPEG文件格式. 我们在系统自带的画图程序里保存文件,在保存类型:JPEG(*.JPG,*.JPEG,*. ...

  6. 移动网页端HTML5 meta便签

    width = device-width:标识宽度是设备屏幕的宽度 initial-scale = 1.0 :标识初始的缩放比例 minimum-scale =0.5 :表示最小的缩放比例 maxim ...

  7. 文件读写FILE类

    1. 新建一个文件: FILE *f = fopen("a.txt","w+"); (1)fopen()函数介绍fopen的原型是:FILE *fopen(co ...

  8. 009 CSS选择器

    CSS选择器 一.基础选择器 1.通配选择器 * { border: solid; } 匹配文档中所有标签:通常指html.body及body中所有显示类的标签 2.标签选择器 div { backg ...

  9. Linux–varnish(一)

    简介 Varnish 是一款高性能且开源的反向代理服务器和 HTTP 加速器,其采用全新的软件体系机构,和现在的硬件体系紧密配合,与传统的 squid 相比,varnish 具有性能更高.速度更快.管 ...

  10. Python模块概念

    补充:生成器表达式 将列表生成器的中括号改为小括号就是生成器表达式 res = [i for i in range(10) if i > 5]  #  列表生成式 res = (i for i ...