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. AngularJS学习笔记之directive——scope选项与绑定策略

    开门见山地说,scope:{}使指令与外界隔离开来,使其模板(template)处于non-inheriting(无继承)的状态,当然除非你在其中使用了transclude嵌入,这点之后的笔记会再详细 ...

  2. Python_@修饰器(装饰器)的理解

    装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能. 装饰器的作用就是为已经存在的对象添加额外的功能. def funA(fun): print (fun( ...

  3. spring 整合 mybatis 中数据源的几种配置方式

    因为spring 整合mybatis的过程中, 有好几种整合方式,尤其是数据源那块,经常看到不一样的配置方式,总感觉有点乱,所以今天有空总结下. 一.采用org.mybatis.spring.mapp ...

  4. Git分支创建与合并

    分支管理是Git支持多人协作和版本控制的关键,参照廖雪峰对Git的介绍,对真实开发环境中Git的使用结合实践进行梳理. 摘自:廖雪峰的官方网站 在实际开发中,我们应该按照几个基本原则进行分支管理: 首 ...

  5. rsync的详细配置

    服务器配置: yum install rsync   安装rsync vi /etc/rsyncd.conf   创建主配置文件 pid file = /var/run/rsyncd.pid port ...

  6. Codable实现json转Model,是时候干掉HandyJSON了!

    自从开始使用Swift做项目,一直都在使用HandyJSON,不可否认,HandyJSON在Swift4.0是个好东西,也尝试过其它json转mode的工具,最终发现还是HandyJSON最好用. 去 ...

  7. Mysql分页查询性能分析

    [PS:原文手打,转载说明出处,博客园] 前言 看过一堆的百度,最终还是自己做了一次实验,本文基于Mysql5.7.17版本,Mysql引擎为InnoDB,编码为utf8,排序规则为utf8_gene ...

  8. codeforces——961A Tetris

    本文是博主原创文章,未经允许不得转载. 我在csdn上也同步发布了此文,链接 https://blog.csdn.net/umbrellalalalala/article/details/798915 ...

  9. Python学习摘要201802

    [基础]变量设计机制 [个人理解]python的变量与C++语言中的指针类似,是指向内存数据的一个引用.变量分为不可变变量string/int/float/tuple和可变变量list/dict. 对 ...

  10. Dubbo学习-源码学习

    Dubbo概述 dubbo框架提供多协议远程调用,服务提供方可以是分布式部署.dubbo框架可以很简单的帮我们实现微服务. 此处援引官网上图片 dubbo分为客户端和服务提供方 服务方将服务注册到注册 ...