【JZOJ3216】【SDOI2013】淘金
╰( ̄▽ ̄)╭
小 Z在玩一个 叫做《淘金者》的游戏。游戏的世界是一个 二维坐标 。X轴、Y轴坐标范围均为1..N。初始的时候,所有的整数坐标点上均有一块金子,共 N*N 块。
一阵风吹过, 金子的位置发生了一些变化。细心的小Z发现, 初始 在(i, j) 坐标 处的金子会变到 (f(i),f(j))坐标 处。其中f(x)表示 x各位数字的乘积 ,例如 ,例如 f(99)=81,f(12)=2,f(10)=0。如果金子变化后的坐标不在 1..N 的范围内,我们认为这块金子已经 被移出游戏。 同时可以发现, 对于变化之后的游戏局面, 某些 坐 标上的金子数量可能 不止一块 ,而另外一些坐标上可能已经没有金子 。这次变化 之后, 游戏将不会再对 金子的位置和数量进行改变,玩家可以开始采集工作。
小 Z很懒 ,打算 只进行 只进行 K次采集 。每次采集可以得到某 一个坐标上的所有 金子 ,采集之后该坐标上的金子数变为 0。
现在小 Z希望知道,对于变化之后的游戏局面,在采集次数为K的前提下, 最多可以采集到少块金子?
答案可能很大,小 Z希望得到1000000007 (10^ 9+7) 取模之后的答案。
(⊙ ▽ ⊙)
横纵坐标可以分开讨论,
为什么?
f()函数只与其中某一个坐标有关。
然后还要注意到一个性质:
由于f()只会是0..9的数之积,所以质因子只会有2,3,5,7。
这个性质保证了,不同的积不会超过50000个,并且可以利用数位动态规划预处理出:
这些积分别出现多少次。
现在考虑使用数位动态规划求出这些积分别出现多少次a[]。
设fi,j,k,l,o,p表示,填了i位数,并且积为2j∗3k∗5l∗7o,且当前的i位数是否小于n的前i位(小于等于时p=0,否则p=1)。
容易转移;
并且也很容易得出每个积分别出现多少次。(满足条件的fi,j,k,l,o,p则对a[2j∗3k∗5l∗7o]贡献)
知道了a[]后,原问题变成找出前k最大的a[i]∗a[j];
做法:
首先对a[]从大到小排序,然后先把所有a[i]∗a[1] (i∈[1,len(a[])])放入线段树的对应位置;
显然对线段树进行k次最值查询;
每次查询后得到最值的位置,把这一位第二项的a[]往后取一位。
( ̄~ ̄)
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#define ll long long
using namespace std;
const char* fin="ex3216.in";
const char* fout="ex3216.out";
const ll inf=0x7fffffff;
const ll maxn=60007,mo=1000000007,maxh=999997,maxt=maxn*8;
ll n,m,i,j,k,l,o,p,index,J,K,L,O,P;
ll A[maxn],len,ans;
ll f[14][40][26][20][15][2],a[40][26][20][15];
struct node{
ll x,y;
}b[maxn];
bool cmp(node a,node b){
return a.y>b.y;
}
ll h[maxh],d[maxh],num;
ll hash(ll x){
ll k=x%maxh;
while (h[k] && h[k]!=x) k=(k+1)%maxh;
return k;
}
ll c[maxt],cc[maxt];
void plant(ll l,ll r,ll t){
ll mid=(l+r)/2;
if (l==r){
cc[t]=1;
c[t]=b[l].y*b[1].y;
return;
}
plant(l,mid,t*2);
plant(mid+1,r,t*2+1);
c[t]=max(c[t*2],c[t*2+1]);
}
ll getmax(ll l,ll r,ll t){
ll mid=(l+r)/2,k;
if (l==r){
k=c[t];
c[t]=b[l].y*b[++cc[t]].y;
return k;
}
if (c[t*2]>c[t*2+1]) k=getmax(l,mid,t*2);
else k=getmax(mid+1,r,t*2+1);
c[t]=max(c[t*2],c[t*2+1]);
return k;
}
int main(){
char ch=getchar();
n=0;
while (ch<='9' && ch>='0') A[++len]=ch-'0',n=n*10+ch-'0',ch=getchar();
for (i=1;i<=len/2;i++) swap(A[i],A[len-i+1]);
scanf("%lld",&m);
f[0][0][0][0][0][0]=1;
a[0][0][0][0]=1;
for (j=0;j<40;j++)
for (k=0;k<26;k++)
for (l=0;l<20;l++)
for (o=0;o<15;o++){
if (j) a[j][k][l][o]=a[j-1][k][l][o]*2;
else if (k) a[j][k][l][o]=a[j][k-1][l][o]*3;
else if (l) a[j][k][l][o]=a[j][k][l-1][o]*5;
else if (o) a[j][k][l][o]=a[j][k][l][o-1]*7;
if (a[j][k][l][o]>n) a[j][k][l][o]=n+1;
}
for (i=0;i<=len;i++)
for (j=0;j<40;j++)
for (k=0;k<26;k++)
for (l=0;l<20;l++)
for (o=0;o<15;o++)
for (p=0;p<2;p++){
if (i<len)
for (index=1;index<=9;index++){
ll tmp=index;
J=K=L=O=P=0;
if (index>A[i+1]) P=1;
else if (index==A[i+1]) P=p;
while (tmp%2==0) tmp/=2,J++;
while (tmp%3==0) tmp/=3,K++;
while (tmp%5==0) tmp/=5,L++;
while (tmp%7==0) tmp/=7,O++;
f[i+1][j+J][k+K][l+L][o+O][P]=(f[i+1][j+J][k+K][l+L][o+O][P]+f[i][j][k][l][o][p])%mo;
}
if (f[i][j][k][l][o][p]>0 && i>0 && (i<len || !p)){
if (a[j][k][l][o]>n){
continue;
}
ll tmp=hash(a[j][k][l][o]);
if (!h[tmp]){
h[tmp]=a[j][k][l][o];
b[d[tmp]=++num].x=a[j][k][l][o];
}
b[d[tmp]].y+=f[i][j][k][l][o][p];
}
}
sort(b+1,b+num+1,cmp);
plant(1,num,1);
for (i=1;i<=m;i++) ans=(ans+getmax(1,num,1))%mo;
printf("%lld",ans);
return 0;
}
(⊙v⊙)
1.对于f(x)这种一元函数,可以单独考虑和讨论。
2.对积的质因子敏感,例如本题,只有2,3,5,7这四个质因子。
【JZOJ3216】【SDOI2013】淘金的更多相关文章
- [BZOJ3131] [Sdoi2013]淘金
[BZOJ3131] [Sdoi2013]淘金 Description 小Z在玩一个叫做<淘金者>的游戏.游戏的世界是一个二维坐标.X轴.Y轴坐标范围均为1..N.初始的时候,所有的整数坐 ...
- [Bzoj3131][Sdoi2013]淘金(数位dp)(优先队列)
3131: [Sdoi2013]淘金 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 847 Solved: 423[Submit][Status][ ...
- Bzoj 3131 [Sdoi2013]淘金 题解
3131: [Sdoi2013]淘金 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 733 Solved: 363[Submit][Status][ ...
- 题解-SDOI2013 淘金
题面 SDOI2013 淘金 有一个 \(X\).\(Y\) 轴坐标范围为 \(1\sim n\) 的范围的方阵,每个点上有块黄金.一阵风来 \((x,y)\) 上的黄金到了 \((f(x),f(y) ...
- bzoj 3131: [Sdoi2013]淘金
#include<cstdio> #include<iostream> #include<queue> #include<algorithm> #def ...
- bzoj 3131 [Sdoi2013]淘金(数位DP+优先队列)
Description 小Z在玩一个叫做<淘金者>的游戏.游戏的世界是一个二维坐标.X轴.Y轴坐标范围均为1..N.初始的时候,所有的整数坐标点上均有一块金子,共N*N块. 一阵风吹 ...
- 【bzoj 3131】[Sdoi2013]淘金
Description 小Z在玩一个叫做<淘金者>的游戏.游戏的世界是一个二维坐标.X轴.Y轴坐标范围均为1..N.初始的时候,所有的整数坐标点上均有一块金子,共N*N块. 一阵风吹 ...
- bozoj3131: [Sdoi2013]淘金 数位dp
链接 https://www.lydsy.com/JudgeOnline/problem.php?id=3131 思路 1. 函数值的素因子只有2.3.5.7 由他们组成的状态不多,爆搜的时候即使搜不 ...
- BZOJ 3131 [SDOI2013]淘金 - 数位DP
传送门 Solution 这道数位$DP$看的我很懵逼啊... 首先我们肯定要先预处理出 $12$位乘起来的所有的可能情况, 记录入数组 $b$, 发现个数并不多, 仅$1e4$不到. 然后我们考虑算 ...
- bzoj千题计划268:bzoj3131: [Sdoi2013]淘金
http://www.lydsy.com/JudgeOnline/problem.php?id=3131 如果已知 s[i]=j 表示有j个<=n数的数码乘积=i 那么就会有 s[a1]*s[a ...
随机推荐
- HDU--2602(0-1背包)
题目:http://acm.hdu.edu.cn/showproblem.php?pid=2602 分析:一个0-1背包问题.记得<背包九讲>的方法. dp[j]=max{dp[j],d ...
- vue:element-ui输入框绑定回车事件
参考: https://segmentfault.com/q/1010000011347642 https://weiku.co/article/297/ vue监听input输入框的回车事件:key ...
- Luogu P3007 [USACO11JAN]大陆议会The Continental Cowngress
P3007 [USACO11JAN]大陆议会The Continental Cowngress 题意 题意翻译 简述:给出\(n\)个法案,\(m\)头牛的意见,每头牛有两个表决格式为"支持 ...
- 自动化运维工具Ansible工具
目录 一.初识Ansible 二.Ansible的架构 三.Ansible基础使用 安装 主机清单 管理主机 四.Ansible用脚本管理主机 五.Ansible模块Module 六.Ansible常 ...
- Python-可变类型与不可变类型
可变类型 可以变化的,列表和字典 利用id()函数 查看内存地址 内存地址变化即不可变类型. 内存地址不变化即可变类型 不可变类型 不可以变化的,字符串和数字 字符串内置方法 索引取值 索引切片 成员 ...
- memcpy 和 memmove
memcpy 原形为: void *memcpy(void *dest, const void *src, size_t n); 其用于内存空间的拷贝,但是并没有考虑内存重叠问题. memmove原形 ...
- SQL server插入数据后,获取自增长字段的值
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 insert into Tb_People(uname,er ...
- win10文件名或文件路径过长导致无法删除或复制的解决办法
试过了百度上的所有方法,命令行中del没有作用,Unlocker也没用,批处理也不起作用,360的强力删除也没有作用. 最后找到一种方法,在压缩该文件的时候选择删除源文件. 但是需要注意一点,用360 ...
- jps的用法及常见问题介绍
1.jps的作用 jps类似linux的ps命令,不同的是ps是用来显示进程,而jps只显示java进程,准确的说是当前用户已启动的部分java进程信息,信息包括进程号和简短的进程command. 2 ...
- 两天了。照着SVN的界面画的一个界面。
可以选择显示哪些列. 界面上的东西,都简单,麻烦的是它的下层.下层全部用svn server的服务器自带的svn.exe来支持. 有些位置要启动svn.exe不止一次.所以参数的来回传递,来回组合 ...