Bzoj 3131 [Sdoi2013]淘金 题解

3131: [Sdoi2013]淘金

Time Limit: 30 Sec  Memory Limit: 256 MB
Submit: 733  Solved: 363
[Submit][Status][Discuss]

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题……

  首先,我们可以发现横纵坐标没有任何关系,完全独立,所以我们真正要做的是求出每个数有多少个数以他为f值。按照套路我们还是应该先dfs一下各种可能的乘积,然后弱到一定地步的我就懵了,乘积得多少种啊,存都存不下,然后事实证明我错了,实践证明我只要打一下表就会发现其实只有八千多个乘积……

  求出来所有乘积之后我们接着按照数位DP的套路搞。不过为了方便,我们把我们得到的所有乘积先去重和离散。设f[i][j][k]为当前我们算到第i位,第i位为j,当前乘积离散后为k的方案数。转移也是很好转移的,直接枚举那一位的数是几就好了。统计答案的时候也是按照套路,先统计位数比n低的,然后将位数从高到低依次统计每一个k答案即可。至于答案。我们用优先队列排序就可以了。

  1 #include <iostream>
  2 #include <cstdlib>
  3 #include <cstdio>
  4 #include <cstring>
  5 #include <algorithm>
  6 #include <cmath>
  7 #include <queue>
  8 #include <map>
  9 #include <set>
 10 #include <vector>
 11 #define N 10005
 12 using namespace std;
 13 long long n;
 14 int k,zz,cnt;
 15 long long c[50],p=1000000007;
 16 long long jg[1000005];
 17 void dfs(long long x,int st,int len)
 18 {
 19     if(len==14)
 20     {
 21         return;
 22     }
 23     zz++;
 24     jg[zz]=x;
 25     for(int i=st;i<=9;i++)
 26     {
 27         dfs(x*i*1ll,i,len+1);
 28     }
 29 }
 30 long long f[15][10][N];
 31 long long ans[N];
 32 long long work(int x)
 33 {
 34     long long sum=0;
 35     for(int i=1;i<cnt;i++)
 36     {
 37         for(int j=1;j<=9;j++)
 38         {
 39             sum+=f[i][j][x];
 40         }
 41     }
 42     long long la=1;
 43     for(int i=cnt;i>0;i--)
 44     {
 45         if(la==0||jg[x]%la||la>jg[x])break;
 46         int t=lower_bound(jg+1,jg+1+zz,jg[x]/la)-jg;
 47         for(int j=1;j<c[i];j++)
 48         {
 49             sum+=f[i][j][t];
 50         }
 51         la*=c[i];
 52     }
 53     return sum;
 54 }
 55 map<int,bool> vi[N];
 56 struct no{
 57     int a,b;
 58     long long data;
 59     bool friend operator < (no a,no b)
 60     {
 61         return a.data<b.data;
 62     }
 63 };
 64 int main()
 65 {
 66     scanf("%lld%d",&n,&k);
 67     zz++;jg[zz]=0;
 68     long long tt=n;
 69     while(tt)
 70     {
 71         cnt++;
 72         c[cnt]=tt%10;
 73         tt/=10;
 74     }
 75     c[1]++;
 76     dfs(1,2,1);
 77
 78     sort(jg+1,jg+zz+1);
 79     zz=unique(jg+1,jg+zz+1)-jg-1;
 80     for(int i=1;i<=9;i++)
 81     {
 82         f[1][i][lower_bound(jg+1,jg+zz+1,i)-jg]=1;
 83     }
 84     for(int i=1;i<cnt;i++)
 85     {
 86         for(int j=1;j<=9;j++)
 87         {
 88             for(int k=1;k<=9;k++)
 89             {
 90                 for(int l=1;l<=zz;l++)
 91                 {
 92                     if(!f[i][j][l])continue;
 93                     if(jg[l]*(long long)k>jg[zz])continue;
 94                     f[i+1][k][lower_bound(jg+1,jg+1+zz,jg[l]*k)-jg]+=f[i][j][l];
 95                 }
 96             }
 97         }
 98     }
 99     for(int i=1;i<=zz;i++)
100     {
101         ans[i]=work(i);
102     }
103     sort(ans+1,ans+zz+1);
104
105     no aa;
106     aa.a=aa.b=zz;
107     aa.data=ans[zz]*ans[zz];
108     priority_queue<no> q1;
109
110     q1.push(aa);
111     long long sum=0;
112     while(k&&!q1.empty())
113     {
114         k--;
115         while(!q1.empty()&&vi[q1.top().a][q1.top().b]) q1.pop();
116         aa=q1.top();q1.pop();
117         sum+=aa.data%p;
118         sum%=p;
119         vi[aa.a][aa.b]=1;
120         aa.a--;
121         aa.data=ans[aa.a]*ans[aa.b];
122         q1.push(aa);
123         aa.a++;aa.b--;
124         aa.data=ans[aa.a]*ans[aa.b];
125         q1.push(aa);
126     }
127     printf("%lld\n",sum);
128     return 0;
129 }

时间: 2024-08-03 16:29:18

Bzoj 3131 [Sdoi2013]淘金 题解的相关文章

[BZOJ 3131][Sdoi2013]淘金

题目连接:http://www.lydsy.com/JudgeOnline/problem.php?id=3131 首先可以想到先算出一维的,再拓展到二维. 我们设g[i]表示各位数字乘积为i的数字个数(<=n),然后可以用堆/优先队列算出二维的前k大. 现在关键是如何求g[i]. 我一开始也不会~\(≧▽≦)/~啦啦啦,但实际上所有乘积总个数只有2e5多(我也不知道为什么有题解说是1e4...可能是我错了吧),将乘积离散化,然后就可以进行数位DP了.具体如下:设f[i][j][k]表示当前算到

BZOJ 3131 SDOI2013 淘金 数位dp

原题链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3131 题意没什么好概述的..... 首先从题目对数的每一位进行相乘的操作以及N的范围可以看出来估计和数位dp有关系. 先考虑一维的情况.可以发现一个数的每一位相乘得到的数字质因数只有2,3,5,7,并且带有0的数字是没有贡献的,同时我们可以简单证明对于题目中的函数f(x)一定有f(x)<x,也即是说所有的f(x)都是在向1靠拢,具体到哪里取决于这个数的质因数. 于是可以令f(i,a,b,

bzoj 3198: [Sdoi2013]spring 题解

[原题] 3198: [Sdoi2013]spring Time Limit: 40 Sec  Memory Limit: 256 MB Submit: 253  Solved: 95 Description Input Output Sample Input 3 3 1 2 3 4 5 6 1 2 3 0 0 0 0 0 0 4 5 6 Sample Output 2 HINT [题解]这道题明明是水题,坑了我两天!!!真是伤心.发现哈希都不熟练了. 首先很容易想到是2^6枚举01状态,使得1

Bzoj 3124: [Sdoi2013]直径 题解

3124: [Sdoi2013]直径 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1222  Solved: 580[Submit][Status][Discuss] Description 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节点,可以证明其有且仅有N-1 条边. 路径:一棵树上,任意两个节点之间最多有一条简单路径.我们用 dis(a,b)表示点a和点

矩阵乘法专题1——bzoj 1297 [SCOI2009] 迷路题解

题目链接 题意:给两个长度分别为n和m的序列,现在有两种操作:1.分别选择两个序列的一个非空前缀,切两个前缀的最后一位相同,删除之,得到1分(只累计),消耗e:2.直接删除两个序列,消耗值定于两个序列之前删除的元素个数之和,并且使得得到的分有效(之前没有有效分) 分析: 首先,问题其实就是转化成,进行若干次操作1,然后进行操作2 还要找到一个判别标准,来评判较优的状态(贪心) 每次的消耗值比较大,其实可以计算出最大的删除次数,这个值不是很大 状态表示: 简单的,一个状态可以表示为串A的位置.串B

BZOJ 1~10 精简题解

从这星期起,我开始了怒刷BZOJ的旅程.这几天刷了10道题(由于"档期"的原因,所以有几道题没打完-..捂脸--..) 精简题解: 1000 A+B Problem --.. [BeiJing2006]狼抓兔子 裸的网络流,不过data有点大...... 哈,这图的性质太好了,就是一个平面图额,并且也很容易转化成对偶图,So--spfa怒跑之-- [FJOI2007]轮状病毒 Matrix-tree定理 不过,这道题有个线性递推式:f[n] = 3 * f[n - 1] – f[I -

bzoj 3246 [Ioi2013] Dreaming 题解

[原题] 3246: [Ioi2013]Dreaming Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 194  Solved: 68 Description Serpent(水蛇)生活的地方有N个水坑,编号为0,...,N - 1,有M条双向小路连接这些水坑.每两个水坑之间至多有一条路径(路径包含一条或多条小路)相互连接,有些水坑之间根本无法互通(即M ≤ N-1 ).Serpent走过每条小路需要一个固定的天数,不同的小路需要的天数可能不同.

splay专题复习——bzoj 3224 &amp; 1862 &amp; 1503 题解

[前言]快要省选二试了.上次去被虐出翔了~~这次即便是打酱油,也要打出风采!于是暂停新东西的学习,然后开始复习以前的知识,为骗分做准备.PS:区间翻转的暂时跳过,就算学了也来不及巩固了. [BZOJ3224] 3224: Tyvj 1728 普通平衡树 Time Limit: 10 Sec  Memory Limit: 128 MB Submit: 1477  Solved: 570 Description 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 1. 插入

bzoj 3333: 排队计划 题解

[原题] 3333: 排队计划 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 161  Solved: 71 [Submit][Status] Description Input Output Sample Input 6 2 160 163 164 161 167 160 2 3 Sample Output 6 3 1 HINT Source wyx528命题 [分析]简述一下题目.N个数排成一列,每次指定一个位置P,然后把P~N中所有身高小