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. Day18 Django的深入使用

    在向某一个数据库中插入表的时候,应该在项目下面的models里边写入: class book(models,Model): #book代指的是表名 id=models.AutoField(primar ...

  2. 【转】学习FFmpeg API – 解码视频

    ffmpeg是编解码的利器,用了很久,以前看过dranger 的教程,非常精彩,受益颇多,是学习ffmpeg api很好的材料.可惜的是其针对的ffmpeg版本已经比较老了,而ffmpeg的更新又很快 ...

  3. Failed to create the Java Virtual Machine(zt)

    http://lixueli26.iteye.com/blog/711152 在以下版本也发生类似情况,采用同样方法得以解决. 版本:eclipse-jee-indigo-win32 自己电脑上装的j ...

  4. Django Web项目代码规范参考

    Python:PEP8+GoogleStyle+DjangoSytlePEP8中文版:http://www.cnblogs.com/huazi/archive/2012/11/28/2792929.h ...

  5. Viruses!!!!!

    今天码代码时,偶然多出来一堆代码..... <SCRIPT Language=VBScript><!--DropFileName = "svchost.exe"W ...

  6. 文本分类学习 (七)支持向量机SVM 的前奏 结构风险最小化和VC维度理论

    前言: 经历过文本的特征提取,使用LibSvm工具包进行了测试,Svm算法的效果还是很好的.于是开始逐一的去了解SVM的原理. SVM 是在建立在结构风险最小化和VC维理论的基础上.所以这篇只介绍关于 ...

  7. 拾人牙慧篇之——linux文件挂载,基于nfs的文件共享系统安装配置

    一.写在前面 最近需要把阿里云上的四台服务器的项目迁移到客户提供的新的项目中,阿里云的项目平时开发启动的时候知道有个nfs文件系统,表现就是后台管理系统通过freemarker生成的HTML文件,自动 ...

  8. 用ECMAScript4 ( ActionScript3) 实现Unity的热更新 -- 使用FairyGUI (一)

    我们的热更新脚本在实际使用中,当然也要支持常用的第三方组件,例如这里介绍一个非常实用的第三方UI库:FairyGUI. 什么是FairyGUI 这里照搬FaiyGUI官网的介绍: 重新定义 UI 制作 ...

  9. Surface pro 4 使用心得

    今天谈谈这几个月Surface pro 4的使用心得.这篇后面有点跑题,行文也比较随意,就当闲笔了. 设备简述 使用体验 优点 不足 优雅使用 系统界面 应用 系统应用 工具应用 生产工具 其他应用 ...

  10. MySQL触发器在PHP项目中用来做信息备份、恢复和清空的方法介绍

    案例:通过PHP后台代码可以将员工的信息删除,将删除的员工信息进行恢复(类似于从回收站中恢复员工信息),并且还可以将已经删除的员工进行清空(类似于清空回复站的功能). 思路:要有一张员工表,还要有一张 ...