思路比较自然,但我要是考场上写估计会写挂;好像被什么不得了的细节苟住了?……

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


题目分析

关键问题在于处理乘积为$i$的数的个数。这个还是一个思路比较自然的dp的。

但是好像有什么不得了的细节恶心到了。

 // luogu-judger-enable-o2
#include<bits/stdc++.h>
typedef long long ll;
const int MO = 1e9+; ll sum[];
struct node
{
int x,y;
ll val;
node(int a=, int b=):x(a),y(b) {}
bool operator < (node a) const
{
return 1ll*sum[x]*sum[y] < 1ll*sum[a.x]*sum[a.y];
}
};
int d[];
ll n,k,cnt,dct,ans;
ll f[][][];
std::map<int, ll> mp1;
std::map<ll, int> mp2;
std::priority_queue<node> q; bool cmp(ll a, ll b){return a > b;}
int main()
{
scanf("%lld%lld",&n,&k);
for (ll i=; i<=n; i*=2ll)
for (ll j=; i*j<=n; j*=3ll)
for (ll k=; i*j*k<=n; k*=5ll)
for (ll l=; i*j*k*l<=n; l*=7ll)
mp1[++cnt] = i*j*k*l, mp2[i*j*k*l] = cnt;
//MAXcnt==14672
for (ll x=n; x; x/=) d[++dct] = x%;
for (int i=; i<=; i++) f[][mp2[i]][i > d[]]++;
for (int t=; t<=dct; t++)
for (int i=; i<=cnt; i++)
for (int j=; j<=; j++)
{
ll num = mp1[i];
if (num%j) continue;
int lb = mp2[num/j];
if (j < d[t])
f[t][i][] += f[t-][lb][]+f[t-][lb][];
else if (j > d[t])
f[t][i][] += f[t-][lb][]+f[t-][lb][];
else f[t][i][] += f[t-][lb][], f[t][i][] += f[t-][lb][];
}
for (int j=; j<=cnt; j++)
for (int i=; i<=dct; i++)
sum[j] += f[i][j][]+(i==dct?:f[i][j][]);
// for (int j=1; j<=cnt; j++)
// for (int i=1; i<=dct; i++)
// sum[j] += f[i][j][0]+(i==dct)?0:f[i][j][1];   //这两个答案是不一样的?……
k = std::min(k, cnt*cnt);
std::sort(sum+, sum+cnt+, cmp);
for (int i=; i<=cnt; i++) q.push(node(i, ));
while (k--)
{
node tt = q.top();
q.pop(), ans = (ans+sum[tt.x]*sum[tt.y]%MO)%MO;
if (tt.y==cnt) continue;
q.push(node(tt.x, tt.y+));
}
printf("%lld\n",ans);
return ;
}

upd:原来$?:$的优先级比$+$低……怪不得很多人写的时候把双目括起来

END

【数位dp】bzoj3131: [Sdoi2013]淘金的更多相关文章

  1. [BZOJ3131] [Sdoi2013]淘金

    [BZOJ3131] [Sdoi2013]淘金 Description 小Z在玩一个叫做<淘金者>的游戏.游戏的世界是一个二维坐标.X轴.Y轴坐标范围均为1..N.初始的时候,所有的整数坐 ...

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

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

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

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

  4. [您有新的未分配科技点]数位DP:从板子到基础(例题 bzoj1026 windy数 bzoj3131 淘金)

    只会统计数位个数或者某种”符合简单规律”的数并不够……我们需要更多的套路和应用 数位dp中常用的思想是“分类讨论”思想.下面我们就看一道典型的分类讨论例题 1026: [SCOI2009]windy数 ...

  5. bzoj 3131 [Sdoi2013]淘金(数位DP+优先队列)

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

  6. BZOJ 3131 [SDOI2013]淘金 - 数位DP

    传送门 Solution 这道数位$DP$看的我很懵逼啊... 首先我们肯定要先预处理出 $12$位乘起来的所有的可能情况, 记录入数组 $b$, 发现个数并不多, 仅$1e4$不到. 然后我们考虑算 ...

  7. [SDOI2013]淘金 数位DP

    做了好久.... 大致思路: 求出前k大的方格之和即为答案, 先考虑一维的情况,设f[i]为数位上各个数相乘为i的数的总数,也就是对于数i,有f[i]个数它们各个位相乘为i, 再拓展到二维,根据乘法原 ...

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

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

  9. 数位DP学习笔记

    数位DP学习笔记 什么是数位DP? 数位DP比较经典的题目是在数字Li和Ri之间求有多少个满足X性质的数,显然对于所有的题目都可以这样得到一些暴力的分数 我们称之为朴素算法: for(int i=l_ ...

随机推荐

  1. 黑马旅游网 ajax+html在前端实现页标签个数控制

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  2. nacos1.0.0 服务管理使用mysql

    在自己的MySQL中添加nacos_config数据库,在nacos\conf 下找到nacos-mysql.sql.拷贝里面的sql语句创建表和数据 INSERT INTO users (usern ...

  3. IOS字符串截取保留小数点后两位

    -(NSString*)getTheCorrectNum:(NSString*)tempString { //计算截取的长度 NSUInteger endLength = tempString.len ...

  4. bzoj1822: [JSOI2010]Frozen Nova 冷冻波网络流

    思路比较显然:二分答案,流流流 但是实现的时候感觉自己数学捉急.. 一开始算了个直线到点距离.... 应该是线段到点距离 #include <bits/stdc++.h> #define ...

  5. php:封装了个时间函数,返回类似“1分钟前发布”,“5小时前发布”,“3年前发布”

    处理和时间有关的时候,像发布问题等通常不会用date格式的时间,而是用类似"3分钟前发布"等格式,下面封装的php函数就可以使用: 注意:当有用到strtotime()函数的记得加 ...

  6. setState异步函数

    changeLeader(value){ console.log(value)   this.setState({   leader:value   },() => {   console.lo ...

  7. windows环境下memcache配置方法 详细篇

    将memcache服务器安装包解压到C:\memcached文件夹后,使用cmd命令窗口安装. 1>开始>运行:CMD(确定) 2>cd C:\memcached(回车) 3> ...

  8. 关于使用memcached提高并发的文章,很有用

    http://blog.csdn.net/ywh147/article/details/9385137 http://phl.iteye.com/category/292555 memcached 解 ...

  9. 基本类型包装类、System类、Math类、Arrays类、大数据运算

    1 基本类型包装类 Java中想对8种基本数据类型进行复杂操作很困难. 实际程序界面上用户输入的数据都是以字符串类型进行存储的. 程序开发中,需要把字符串转换成指定的基本数据类型. 1.1基本数据类型 ...

  10. js控制语句

    1 条件判断语句 条件语句用于基于不同的条件来执行不同的动作. 1.1if 语句 if (condition){    当条件为 true 时执行的代码} 1.2if...else 语句 if (co ...