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答案即可。至于答案。我们用优先队列排序就可以了。
 #include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <map>
#include <set>
#include <vector>
#define N 10005
using namespace std;
long long n;
int k,zz,cnt;
long long c[],p=;
long long jg[];
void dfs(long long x,int st,int len)
{
if(len==)
{
return;
}
zz++;
jg[zz]=x;
for(int i=st;i<=;i++)
{
dfs(x*i*1ll,i,len+);
}
}
long long f[][][N];
long long ans[N];
long long work(int x)
{
long long sum=;
for(int i=;i<cnt;i++)
{
for(int j=;j<=;j++)
{
sum+=f[i][j][x];
}
}
long long la=;
for(int i=cnt;i>;i--)
{
if(la==||jg[x]%la||la>jg[x])break;
int t=lower_bound(jg+,jg++zz,jg[x]/la)-jg;
for(int j=;j<c[i];j++)
{
sum+=f[i][j][t];
}
la*=c[i];
}
return sum;
}
map<int,bool> vi[N];
struct no{
int a,b;
long long data;
bool friend operator < (no a,no b)
{
return a.data<b.data;
}
};
int main()
{
scanf("%lld%d",&n,&k);
zz++;jg[zz]=;
long long tt=n;
while(tt)
{
cnt++;
c[cnt]=tt%;
tt/=;
}
c[]++;
dfs(,,); sort(jg+,jg+zz+);
zz=unique(jg+,jg+zz+)-jg-;
for(int i=;i<=;i++)
{
f[][i][lower_bound(jg+,jg+zz+,i)-jg]=;
}
for(int i=;i<cnt;i++)
{
for(int j=;j<=;j++)
{
for(int k=;k<=;k++)
{
for(int l=;l<=zz;l++)
{
if(!f[i][j][l])continue;
if(jg[l]*(long long)k>jg[zz])continue;
f[i+][k][lower_bound(jg+,jg++zz,jg[l]*k)-jg]+=f[i][j][l];
}
}
}
}
for(int i=;i<=zz;i++)
{
ans[i]=work(i);
}
sort(ans+,ans+zz+); no aa;
aa.a=aa.b=zz;
aa.data=ans[zz]*ans[zz];
priority_queue<no> q1; q1.push(aa);
long long sum=;
while(k&&!q1.empty())
{
k--;
while(!q1.empty()&&vi[q1.top().a][q1.top().b]) q1.pop();
aa=q1.top();q1.pop();
sum+=aa.data%p;
sum%=p;
vi[aa.a][aa.b]=;
aa.a--;
aa.data=ans[aa.a]*ans[aa.b];
q1.push(aa);
aa.a++;aa.b--;
aa.data=ans[aa.a]*ans[aa.b];
q1.push(aa);
}
printf("%lld\n",sum);
return ;
}

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

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

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

  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 3124: [Sdoi2013]直径 题解

    3124: [Sdoi2013]直径 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1222  Solved: 580[Submit][Status] ...

  6. [Bzoj3131][Sdoi2013]淘金(数位dp)(优先队列)

    3131: [Sdoi2013]淘金 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 847  Solved: 423[Submit][Status][ ...

  7. 题解-SDOI2013 淘金

    题面 SDOI2013 淘金 有一个 \(X\).\(Y\) 轴坐标范围为 \(1\sim n\) 的范围的方阵,每个点上有块黄金.一阵风来 \((x,y)\) 上的黄金到了 \((f(x),f(y) ...

  8. BZOJ 1003 物流运输 题解 【SPFA+DP】

    BZOJ 1003 物流运输 题解 Description 物流公司要把一批货物从码头A运到码头B.由于货物量比较大,需要n天才能运完.货物运输过程中一般要转停好几个码头.物流公司通常会设计一条固定的 ...

  9. BZOJ 1191 超级英雄 Hero 题解

    BZOJ 1191 超级英雄 Hero 题解 Description 现在电视台有一种节目叫做超级英雄,大概的流程就是每位选手到台上回答主持人的几个问题,然后根据回答问题的多少获得不同数目的奖品或奖金 ...

随机推荐

  1. PySide——Python图形化界面入门教程(三)

    PySide——Python图形化界面入门教程(三) ——使用内建新号和槽 ——Using Built-In Signals and Slots 上一个教程中,我们学习了如何创建和建立交互widget ...

  2. C/C++网络编程时注意的问题小结

    1.网络编程在自己定义结构体实现协议的时候,一定要注意字节对齐这个问题.否则sizeof和强制转换指针的时候都会出现很难发现的bug. 什么是字节对齐自行百度. #pragma pack (1)//字 ...

  3. EPPlus导出两千万记录的测试代码

    采用导入100w条记录一个文件,然后合并的方式 using System; using System.IO; using OfficeOpenXml; using System.Data; using ...

  4. SQL Server 将某一列的值拼接成字符串

    名称 海鲜水产 水果蔬菜 海参 肉禽蛋 牛排 腊味 生鲜食品 将以上一列变成: 生鲜食品,海鲜水产,水果蔬菜,海参,牛排,肉禽蛋,腊味 sql for xml path('')

  5. Delphi的对象注销方法Destroy和free

    当您使用完对象后,您应该及时撤销它,以便把这个对象占用的内存释放出来.您可以通过调用一个注销方法来撤销您的对象,它会释放分配给这个对象的内存. Delphi的注销方法有两个:Destroy和Free. ...

  6. 给 Web 开发人员推荐的通用独立 UI 组件(二)

    现代 Web 开发在将体验和功能做到极致的同时,对于美观的追求也越来越高.在推荐完图形库之后,再来推荐一些精品的独立 UI 组件.这些组件可组合在一起,形成美观而交互强大的 Web UI . 给 We ...

  7. spring3升级到spring4通用异常处理返回jsonp多了/**/的解决办法

    问题描述 在spring3中定义了通用的异常处理,具体代码如下: public class CommonExceptionHandler implements HandlerExceptionReso ...

  8. uni-app中Vuex的引用

    //store 中 store.js import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex) const store = new Vue ...

  9. Spark之从hdfs读取数据

    /user/hive/warehouse/ycapp.db/appindex") ), e(),e().toInt)) (String, String, String) ,,all_post ...

  10. java中Array和ArrayList区别

    1)精辟阐述:可以将 ArrayList想象成一种“会自动扩增容量的Array”. 2)Array([]):最高效:但是其容量固定且无法动态改变:     ArrayList:  容量可动态增长:但牺 ...