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$排个序,然后贪心即可。

代码:

  

  1 #define Troy 10/11/2017
  2
  3 #include <bits/stdc++.h>
  4
  5 using namespace std;
  6
  7 typedef long long ll;
  8
  9 const ll mod=1e9+7;
 10
 11 inline ll read(){
 12     ll s=0,k=1;char ch=getchar();
 13     while(ch<'0'|ch>'9')    ch=='-'?k=-1:0,ch=getchar();
 14     while(ch>47&ch<='9')    s=s*10+(ch^48),ch=getchar();
 15     return s*k;
 16 }
 17
 18 const int N=1e6;
 19
 20 ll has[N];int num,p[20],tot;
 21
 22 inline void dfs(ll x,int from,int step){
 23     if(step>12) return ;
 24     has[++num]=x;
 25     for(;from<10;from++){
 26         dfs(x*from,from,step+1);
 27     }
 28 }
 29
 30 ll f[15][15][10000],n,k,ans[10000];//f[i][j][k]:i位开头为j乘积为k的答案
 31
 32 inline void init(){
 33     has[++num]=0;
 34     dfs(1,2,0);
 35     sort(has+1,has+num+1);
 36     num=unique(has+1,has+num+1)-has-1;//    printf("num=%d\n",num);
 37     for(int i=1;i<=9;i++)
 38         f[1][i][lower_bound(has+1,has+num+1,i)-has]=1;
 39     for(int i=2;i<=13;i++){
 40         for(int j=1;j<10;j++){
 41             for(int k=1;k<10;k++)
 42                 for(int l=1;l<=num;l++){
 43                     if(f[i-1][k][l]==0) continue;
 44                     int x;
 45                     if(has[l]*j<=has[num]){
 46                         x=lower_bound(has+1,has+num+1,has[l]*j)-has;
 47                         f[i][j][x]+=f[i-1][k][l];
 48                     }
 49                 }
 50         }
 51     }
 52     do{
 53         p[++tot]=n%10;
 54         n/=10;
 55     }while(n);
 56 }
 57
 58 inline ll calc(int pos){
 59     ll ret=0;
 60     for(int i=1;i<tot;i++){
 61         for(int j=1;j<=9;j++){
 62             ret+=f[i][j][pos];
 63         }
 64     }
 65     ll last=1;
 66     for(int i=tot;i;i--){
 67         if(last>has[pos]||last==0||has[pos]%last!=0)    break;
 68         for(int j=1;j<p[i];j++){
 69             int x=lower_bound(has+1,has+1+num,has[pos]/last)-has;
 70             ret+=f[i][j][x];
 71         }
 72         last*=p[i];
 73     }
 74     return ret%mod;
 75 }
 76
 77 bool vis[9000][9000];
 78
 79 struct node {
 80     int pos[2];ll val;
 81     friend bool operator <(node a,node b){
 82         return a.val!=b.val?a.val<b.val:a.pos[0]!=b.pos[0]?a.pos[0]>b.pos[0]:a.pos[1]>b.pos[1];
 83     }
 84 };
 85
 86 priority_queue<node> q;
 87
 88 int main(){
 89     n=read(),k=read();
 90     n++;
 91     init();
 92     for(int i=2;i<=num;i++)
 93       ans[i]=calc(i);
 94     sort(ans+2,ans+num+1);
 95     q.push((node){num,num,ans[num]*ans[num]});
 96     ll ret=0;
 97     while(k&&(!q.empty())){
 98         k--;
 99         node now;
100         do{
101             now=q.top();q.pop();
102         }while(vis[now.pos[0]][now.pos[1]]&&(!q.empty()));
103         if(!vis[now.pos[0]][now.pos[1]]){
104             ret+=now.val;
105             ret%=mod;
106             if(now.pos[0]>2)
107                 q.push((node){now.pos[0]-1,now.pos[1],ans[now.pos[0]-1]*ans[now.pos[1]]});
108             if(now.pos[1]>2)
109                 q.push((node){now.pos[0],now.pos[1]-1,ans[now.pos[0]]*ans[now.pos[1]-1]});
110         }
111         vis[now.pos[0]][now.pos[1]]=true;
112     }
113     printf("%lld\n",ret);
114 }

转载于:https://www.cnblogs.com/Troywar/p/7651086.html

【bzoj 3131】[Sdoi2013]淘金相关推荐

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

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

  2. BZOJ 3131 [Sdoi2013]淘金

    题解: 首先要看出行列独立 令f[i]表示挂到i点的数量 则(i,j)的金币数量为f[i]*f[j] 然后数位DP求出f[i] 转载于:https://www.cnblogs.com/zzyer/p/ ...

  3. 3131: [Sdoi2013]淘金

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3131 思路:人生第一道数位dp,,,解锁了人生新成就,,, 数位dp的一般思路,分为两步:1 ...

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

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

  5. 淘金(bzoj 3131)

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

  6. [数位dp][优先队列] Bzoj 3131 淘金

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

  7. [SDOI2013] 淘金

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

  8. ●BZOJ 3129 [Sdoi2013]方程

    题链: http://www.lydsy.com/JudgeOnline/problem.php?id=3129 题解: 容斥,扩展Lucas,中国剩余定理 先看看不管限制,只需要每个位置都是正整数时 ...

  9. BZOJ 3203 Sdoi2013 保护出题人 凸包+三分

    题目大意:太长自己看 令sumi表示第i个僵尸以及之前的僵尸的体力总和.disi表示第i个僵尸与房屋的初始距离 我们发现我们能消灭一个僵尸当且仅当y>=sumidisi 那么我们要求的显然就是m ...

  10. P3303 [SDOI2013]淘金

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

最新文章

  1. java整数转二进制字符串_在Java中将int转换为二进制字符串表示形式?
  2. 什么是Python蛋?
  3. 重装 Linux 记录
  4. HDU1561 The more, The Better
  5. shell编程之条件语句(文件测试,test命令,字符串和逻辑测试,if单支语句,if双支语句,if多支语句,case命令,用if写跑步小实验)
  6. VMware Workstation All Key
  7. python中os模块_Python的武器库11:os模块
  8. 制作GHOST XP 基于自由天空驱动包+SysPacker 2.1
  9. android开发那些事儿(二)--Drawable资源
  10. 源码解析:init-method、@PostConstruct、afterPropertiesSet孰先孰后
  11. 网络服务器管理系统设置实训总结,网络系统管理与维护实训报告.doc
  12. 多媒体网路multimedianetworkingCDN的全称是Content Delivery NetworkSIP(Session Initiation Protocol)是一个应用层的信
  13. 暗黑破坏神不朽怎么在电脑上玩 暗黑破坏神不朽模拟器教程
  14. GNSS数据下载网址整理
  15. 自然人机交互到底“自然”在哪儿?
  16. 主板知识详解:主板结构
  17. [ECCV2018]Generating 3D faces using Convolutional Mesh Autoencoders
  18. java 替换字母_【Java项目】将字符串中的字母全部替换成字母的下一个字母
  19. FinalShell密码找回
  20. 回文是指正读反读均相同的字符序列,如“abba”和“abdba”均是回文但“good”不是回文,试写一个算法判断给定字符是否为回文。

热门文章

  1. c#file过滤多种格式_[C#].NET/C#应用程序开发中使用Directory.GetFiles()过滤多种文件扩展名类型有哪些方法?...
  2. html语言format,HTML 文本格式化
  3. python中赋值与c语言区别,python中赋值与c语言区别
  4. iview 自定义时间选择器组件_视图更新科技发布View UI组件库(即 iView 4.0),超过50项更新...
  5. python mysql传入多个参数
  6. DeepFake技术--Deepfakes教程及各个换脸软件下载
  7. Caffe学习:pycaffe利用caffemodel进行分类=裁剪图片
  8. Python获取二维矩阵每列最大值
  9. 网站后台开发 java_Java前后台开发
  10. java操作字节码_操作Java字节码