【JZOJ3216】【SDOI2013】淘金
来源:互联网 发布:单片机红外发射程序 编辑:程序博客网 时间:2024/04/27 18:20
╰( ̄▽ ̄)╭
小 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) 取模之后的答案。
(⊙ ▽ ⊙)
横纵坐标可以分开讨论,
为什么?
然后还要注意到一个性质:
由于
这个性质保证了,不同的积不会超过
这些积分别出现多少次。
现在考虑使用数位动态规划求出这些积分别出现多少次
设
容易转移;
并且也很容易得出每个积分别出现多少次。(满足条件的
知道了
做法:
首先对
显然对线段树进行
每次查询后得到最值的位置,把这一位第二项的
( ̄~ ̄)
#include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#define ll long longusing 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.对于
2.对积的质因子敏感,例如本题,只有
- 【JZOJ3216】【SDOI2013】淘金
- SDOI2013 淘金
- 【SDOI2013】淘金
- 3131: [Sdoi2013]淘金
- BZOJ 3131 [Sdoi2013] 淘金
- bzoj 3131: [Sdoi2013]淘金 数位dp+堆
- 淘金
- [Sdoi2013]assassin
- [Sdoi2013]spring
- [Sdoi2013]escape
- [Sdoi2013]项链
- [Sdoi2013]城市规划
- 【SDOI2013】直径
- 【SDOI2013】方程
- 【SDOI2013】项链
- [Sdoi2013]直径
- 【SDOI2013】森林
- SDOI2013 森林
- hi3520d烧写开发板遇到的问题及其解决方法
- MXNet官方文档教程(6):神经网络图
- 大败局I,多元化是个陷阱吗?
- node.js入门
- 2016年
- 【JZOJ3216】【SDOI2013】淘金
- Angular企业级开发(7)-MVC之控制器
- 【LeetCode 12】 Integer to Roman
- Zookeeper应用场景
- android65535问题
- 最短路径算法
- Windows下Java JDK的安装与配置
- HDU1251 统计难题(trie树[重做])
- Maven的pom.xml介绍