【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這四個質因子。
轉載于:https://www.cnblogs.com/hiweibolu/p/6714789.html
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的【JZOJ3216】【SDOI2013】淘金的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 变量、作用域与内存
- 下一篇: jenkins自动化打包部署