1. 程式人生 > >【BZOJ3131】淘金(SDOI2013)-數位DP+優先佇列

【BZOJ3131】淘金(SDOI2013)-數位DP+優先佇列

測試地址:淘金
做法: 本題需要用到數位DP+優先佇列。
F ( x , y ) F(x,y) 為座標 (

x , y ) (x,y) 上的黃金數目,那麼:
F ( x ,
y ) = i = 1 n
j = 1 n
[ f ( i ) = x ] [ f ( j ) = y ] F(x,y)=\sum_{i=1}^n\sum_{j=1}^{n}[f(i)=x]\cdot[f(j)=y]

= ( i = 1 n [ f ( i ) = x ] ) ( j = 1 n [ f ( j ) = y ] ) =(\sum_{i=1}^n[f(i)=x])\cdot (\sum_{j=1}^n[f(j)=y])
g ( x ) = i = 1 n [ f ( i ) = x ] g(x)=\sum_{i=1}^n[f(i)=x] ,那麼我們只需要求出 g ( x ) g(x) 中的前 k k 大值, F ( x , y ) = g ( x ) g ( y ) F(x,y)=g(x)\cdot g(y) 中的最大值就肯定是由這些 g ( x ) g(x) 組成的了。
然而對於 1 x 1 0 12 1\le x\le 10^{12} ,不同的 f ( x ) f(x) 貌似很多,有 1 0 12 10^{12} 個?或是 9 12 9^{12} 個(因為本題中不考慮 0 0 )?怎麼看都不可能直接進行計算。
然而實際上,我們可以證明 f ( x ) f(x) 的範圍遠沒有那麼大。注意到 f ( x ) f(x) 是若干個 1 1 ~ 9 9 之間的數的乘積,因此它的質因子只有 2 , 3 , 5 , 7 2,3,5,7 ,這就已經排除掉了很多數字了。進一步地, 2 2 最多有 36 36 個( 12 12 8 8 ), 3 3 最多有 24 24 個( 12 12 9 9 ), 5 5 7 7 最多有 12 12 個, 36 × 24 × 12 × 12 = 124416 36\times 24\times 12\times 12=124416 ,這就已經是個很小的上界了。而根據打表的結果,實際上可能達到的不同的 f ( x ) f(x) 的數目只有 11015 11015 個。那麼我們只需對於這些 f ( x ) f(x) 計算對應的 g g 的值即可。
於是顯然有數位DP的狀態定義:令 d p ( i , j , 0 / 1 ) dp(i,j,0/1) 為前 i i 位,滿足 f ( x ) = j f(x)=j 的不卡/卡上界的 x x 的數量,那麼轉移就很容易了。顯然時間複雜度可以接受。
那麼我們求出了 g ( x ) g(x) ,用它來算前 k k 大的 F ( x , y ) F(x,y) ,就和一提高-難度經典題很像了:給兩個序列 A , B A,B ,求 A i + B j A_i+B_j 的前 k k 大值。做法完全一樣,用優先佇列就可以解決這個問題了,時間複雜度為 O ( k log k ) O(k\log k)
祝賀自己又成功想出一道黑題(雖然個人感覺沒有黑題的難度),併成功衝入BZOJ時間榜第七名,可喜可賀。
以下是本人程式碼:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1000000007;
ll x,cnt[20][20010]={0},g[20010];
int k,tot=1,st[20010][4]={0},id[40][30][20][20]={0};
int s[20],n,p[10][4]={0},pr[4]={2,3,5,7},now=1;
int nowp[20010];
struct point
{
	int id;
	ll val;
	bool operator < (point a) const
	{
		return val<a.val;
	}
};
priority_queue<point> Q;

void checkin(int i,int j,int k,ll val,bool type)
{
	int nxt[4],nxts;
	for(int l=0;l<4;l++)
		nxt[l]=st[j][l]+p[k][l];
	if (!id[nxt[0]][nxt[1]][nxt[2]][nxt[3]])
	{
		id[nxt[0]][nxt[1]][nxt[2]][nxt[3]]=++tot;
		for(int l=0;l<4;l++)
			st[tot][l]=nxt[l];
	}
	nxts=id[nxt[0]][nxt[1]][nxt[2]][nxt[3]];
	cnt[i][nxts]=(cnt[i][nxts]+val)%mod;
	if (type) now=nxts;
}

void solve()
{
	now=1;
	for(int i=n;i>=1;i--)
	{
		int lasttot=tot;
		for(int j=1;j<=lasttot;j++)
			for(int k=1;k<=9;k++)
				checkin(i,j,k,cnt[i+1][j],0);
		
		if (now)
		{
			if (i<n)
			{
				for(int j=1;j
            
           

相關推薦

BZOJ3131淘金SDOI2013-數位DP+優先佇列

測試地址:淘金 做法: 本題需要用到數位DP+優先佇列。 令 F ( x

BZOJ3131淘金SDOI2013-數位DP

測試地址:淘金 做法: 本題需要用到數位DP。 令F(x,y)F(x,y)F(x,y)為座標(x,y)(x,y)(x,y)上的黃金數目,那麼: F(x,y)=∑i=1n∑j=1n[f(i)=x]⋅[f(

BZOJ4513儲能表SDOI2016-數位DP

測試地址:儲能表 做法: 本題需要用到數位DP。 顯然地,我們可以把問題轉化成,計算滿足這些條件: i ≤

BZOJ3326數數SCOI2013-數位DP

測試地址:數數 題目大意: 給定L,RL,RL,R兩個10510^5105位內的B(≤105)B(\le 10^5)B(≤105)進位制數,L≤RL\le RL≤R,對區間[L,R][L,R][L,R]內的所有數xxx,累加xxx中所有子串表示的數字的和(如12

java簡介

編碼 http ... 設計 適合 不能 高度 代碼格式 操作系統 應用:web後端開發、android-app開發、大數據應用開發 學習:java會過時,但程序設計的思想不會過時 特點:1、面向對象,跨平臺,語法比c++簡單     2、以字節碼的形式運行在虛擬機上   

JavaDateUtil2

繼承 ava sim pla bool private throw ons tar import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat;

USACO15FEB審查黃金Censoring (Gold)

clu amp del lease sed better n) truct mos 題目描述 Farmer John has purchased a subscription to Good Hooveskeeping magazine for his cows, so

BZOJ2940條紋博弈論

span char 一個 處理 || long long 簡單 sizeof .com 【BZOJ2940】條紋(博弈論) 題面 BZOJ 神TM權限題。 題解 我們把題目看成取石子的話,題目就變成了這樣: 有一堆\(m\)個石頭,每次可以取走\(c,z,n\)個,每次取完

學習reactjs——使用npm創建react項目並整合elementUI

web -s from 頁面 rain tle export build head 在實習的過程中了解了react,所以打算使用react搭建一個屬於自己的頁面,如有問題請教正,謝謝。 Github:https://github.com/yclxt/react-elemen

CF1068BLCM數學

div amp pri stream color can con scan namespace 題意:給定b,求lcm(a,b)/a有幾種不同的取值 b<=1e10 思路:只有a取b的因子時答案兩兩不同 1 #include<cstdio> 2 #i

HDOJ5510BazingaKMP

題意:給定n個由小寫字母組成的字串,第i個字串為a[i],求最大的j滿足存在1<=i<j,a[i]不是a[j]的子串,無解輸出-1 T<=50,n<=500,len[i]<=2000 思路:隊友寫的,抱大腿 判斷某個串是否是另一個串的子串可以使用KMP 有一個優化:若a[

BZOJ3351RegionsIOI2009-分塊+vector

測試地址:Regions 題目大意: 給定一棵 n n n個點的有根樹,每個點有顏色,

BZOJ1432函式ZJOI2009-思維

測試地址:函式 做法: 本題需要用到思維。 如果在 x x x座標為負無窮時,把函式從下到上編號為

C++向量vector 基本使用方法及注意事項

介紹: 向量(Vector)是一個封裝了動態大小陣列的順序容器(Sequence Container)。跟任意其它型別容器一樣,它能夠存放各種型別的物件。可以簡單的認為,向量是一個能夠存放任意型別的動態陣列。 特點: 1.順序序列 順序容器中的元素按照嚴格的線性順序排序。可以通過元素

leetcode50.Medium Pow(x,n)

題目連結 解題思路: 這道題的意思就是求x的n次方。 如果xx求下去,求n-1次,這樣是超時的。 我的思路是,首先求xx,然後n就可以減少2,然後求(xx)(x*x),這樣n就可以減少4… 就是n不是-1、-1、-1…這樣減下去,而是-2、-4、-8…這樣減下去 迭代cnt次後,

leetcode48.MediumRotate Image

題目連結 解題思路: 首先如果二維陣列是11或者22,直接蠻力計算; 如果是22以上,可以一圈一圈(rotate circle)地計算反轉90度之後的結果。 比如,對於下面55的陣列: 首先設定一個數組tmp將框1中的數字儲存起來, 然後計算翻轉後框1(top layer)中的

leetcode47.MediumPermutationsII

題目連結 解題思路: 參考 首先進行排序; 如果陣列中沒有重複的數字,就按照permutations的方法來做就可以了; 如果陣列中有2個重複的數字,比如[1,1,3],首先將陣列分為[1]和[1,3], 對[1,3]進行全排列有[1,3]和[3,1],在所有子全排列中

leetcode46. Medium Permutations

題目連結 解題思路: 這道題的意思就是給你一組數,其中的數字都不一樣,然後求這些數字所有的全排列組合。 比較簡單的思路是: 1.首先如果陣列中只有一個數比如2,那就只返回這個數構成的全排列; 2.如果有兩個數比如1,2那先求2全排列,可以得到[[2]], 然後在這些子全排

POJ1068Parencodings模擬

題目連結 Parencodings Time Limit: 1000MS   Memory Limit: 10000K Total Submissions:28556  

物理電磁

散度divergence,顧名思義,是指一個向量場發散的程度。一個向量場 的散度是一個標量場(向量場的每一點有一個自己的散度),寫作 (這個寫法也很直白,因為點乘就是標量)。如果一個點的散度為正,那麼在這一點上 有向外發散的趨勢;如果為負,那麼在這一點上 有向內收斂的趨勢。 旋