1. 程式人生 > >[BZOJ3598][Scoi2014]方伯伯的商場之旅(數位 DP)

[BZOJ3598][Scoi2014]方伯伯的商場之旅(數位 DP)

Address

洛谷 P3286
BZOJ 3598
LOJ #2215

Solution

  • NOIP 2018 後的第一篇博文,一個新的開始
  • 眾所周知,數軸上有一個點集,求一個點到這些點的距離之和最小
  • 則這個點的座標是這些點的座標的中位數
  • 而此題顯然是一個數位 DP
  • 詢問拆成 [ 0 , R
    ] [0,R]
    [ 0 , L 1
    ] [0,L-1]
  • 下面只討論 [ 0 , R ]
    [0,R]
  • 定義狀態(下面的「位」都是從低到高
  • f [ i ] [ j ] [ 0 / 1 / 2 ] f[i][j][0/1/2] 表示第 1 1 位到第 i i 位,用的數字之和為 j j ,小於 / 等於 / 大於 R R 的第 1 1 位到第 i i 位的方案數
  • f c [ i ] [ j ] [ 0 / 1 / 2 ] fc[i][j][0/1/2] 表示第 1 1 位到第 i i 位,用的數字之和為 j j ,小於 / 等於 / 大於 R R 的第 1 1 位到第 i i 位的所有數的數字之和
  • g [ i ] [ j ] [ 0 / 1 / 2 ] g[i][j][0/1/2] 表示第 i i 位到第 m m 位,用的數字之和為 j j ,小於 / 等於 / 大於 R R 的第 i i 位到第 m m 位的方案數
  • g c [ i ] [ j ] [ 0 / 1 / 2 ] gc[i][j][0/1/2] 表示第 i i 位到第 m m 位,用的數字之和為 j j ,小於 / 等於 / 大於 R R 的第 i i 位到第 m m 位的所有數的數字之和
  • m m R R 的位數
  • 大力轉移
  • 統計 [ 0 , R ] [0,R] 的結果時,考慮列舉中位數所在的位置 i i 和位置 i i 的值 j j
  • 注意, j j 不能等於 0 0
  • 然後列舉比 i i 低的位的數字之和 k k
  • 還有比 i i 高的位的數字之和 h h
  • 通過 k k h h j j 判斷中位數是否在 i i 位置
  • 再用 g ( c ) [ i + 1 ] [ h ] [ 0 / 1 / 2 ] g(c)[i+1][h][0/1/2] f ( c ) [ i 1 ] [ k ] [ 0 / 1 / 2 ] f(c)[i-1][k][0/1/2] 統計答案
  • 注意需要根據具體情況決定第三維下標 0 / 1 / 2 0/1/2 是否可以使用
  • 並特判 i = m i=m i = 1 i=1 的情況

Code

#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define For(i, a, b) for (i = a; i <= b; i++)
#define Rof(i, a, b) for (i = a; i >= b; i--)

typedef long long ll;

const int N = 70, M = 250;

ll L, R, f[N][M][3], g[N][M][3], fc[N][M][3], gc[N][M][3];
int K, tot, a[N];

ll jiejuediao(ll n)
{
	if (n < K) return 0;
	tot = 0;
	while (n) a[++tot] = n % K, n /= K;
	memset(f, 0, sizeof(f));
	memset(g, 0, sizeof(f));
	memset(fc, 0, sizeof(fc));
	memset(gc, 0, sizeof(gc));
	int i, j, k, h, o1, o2, m = tot * (K - 1);
	ll ans = 0;
	For (i, 0, K - 1)
	{
		int op = i > a[1] ? 2 : (i == a[1] ? 1 : 0);
		f[1][i][op]++; fc[1][i][op] += i;
		op = i > a[tot] ? 2 : (i == a[tot] ? 1 : 0);
		g[tot][i][op]++; gc[tot][i][op] += i * tot;
	}
	For (i, 2, tot) For (j, 0, m) For (k, 0, K - 1)
	{
		if (k > j) break;
		if (k < a[i])
		{
			f[i][j][0] += f[i - 1][j - k][0] + f[i - 1][j - k][1]
				+ f[i - 1][j - k][2];
			fc[i][j][0] += fc[i - 1][j - k][0] + fc[i - 1][j - k][1]
				+ fc[i - 1][j - k][2] + (f[i - 1][j - k][0]
				+ f[i - 1][j - k][1] + f[i - 1][j - k][2]) * i * k;
		}
		else if (k > a[i])
		{
			f[i][j][2] += f[i - 1][j - k][0] + f[i - 1][j - k][1]
				+ f[i - 1][j - k][2];
			fc[i][j][2] += fc[i - 1][j - k][0] + fc[i - 1][j - k][1]
				+ fc[i - 1][j - k][2] + (f[i - 1][j - k][0]
				+ f[i - 1][j - k][1] + f[i - 1][j - k][2]) * i * k;
		}
		else
		{
			f[i][j][0] += f[i - 1][j - k][0];
			fc[i][j][0] += fc[i - 1][j - k][0] + f[i - 1][j - k][0] * i * k;
			f[i][j][1] += f[i - 1][j - k][1];
			fc[i][j][1] += fc[i - 1][j - k][1] + f[i - 1][j - k][1] * i * k;
			f[i][j][2] += f[i - 1][j - k][2];
			fc[i][j][2] += fc[i 
            
           

相關推薦

BZOJ3598 SCOI2014伯伯商場數位dp

一個數 bzoj3 根據 clu long long stream 由於 bsp div   看到數據範圍就可以猜到數位dp了。顯然對於一個數最後移到的位置應該是其中位數。於是考慮枚舉移到的位置,那麽設其左邊和為l,左右邊和為r,該位置數為p,則需要滿足l+p>=r且

[BZOJ3598][Scoi2014]伯伯商場數位 DP

Address 洛谷 P3286 BZOJ 3598 LOJ #2215 Solution NOIP 2018 後的第一篇博文,一個新的開始 眾所周知,數軸上有一個點集,求一個點到這些點的距離之和最小 則這個點的座標是這些點的座標的中位數 而此題顯然是一

bzoj 3598: [Scoi2014]伯伯商場數位dp

scan clu cpp ems turn htm main ostream spa 參考了這個http://www.cnblogs.com/Artanis/p/3751644.html,好像比一般方法好寫 大概思想就是先計算出把所有石子都合並到1位置的代價,這樣顯然有一些

BZOJ 3679 數字數位DP

一個數x各個數位上的數之積記為f(x) <不含前導零> 求[L,R)中滿足0<f(x)<=n的數的個數 Input 第一行一個數n 第二行兩個數L、R Output 一個數,即滿足條件的數的個數 Sample Input 5 19 22 Sampl

bzoj3598 [Scoi2014]伯伯商場

tput 記憶化 位統計 進制數 分隔 bsp amp res namespace Description 方伯伯有一天去參加一個商場舉辦的遊戲。商場派了一些工作人員排成一行。每個人面前有幾堆石子。說來也巧,位置在 i 的人面前的第 j 堆的石子的數量,剛好是 i 寫

洛谷3287 [SCOI2014]伯伯的玉米田DP樹狀陣列

題目 方伯伯在自己的農田邊散步,他突然發現田裡的一排玉米非常的不美。這排玉米一共有N株,它們的高度參差不齊。方伯伯認為單調不下降序列很美,所以他決定先把一些玉米拔高,再把破壞美感的玉米拔除掉,使得剩下的玉米的高度構成一個單調不下降序列。方伯伯可以選擇一個區間,把這個區間的玉米全部拔高1單位高

「SHOI2002」「LuoguP1291」百事世界盃UVA10288 Coupons期望,輸出

題目描述 “……在2002年6月之前購買的百事任何飲料的瓶蓋上都會有一個百事球星的名字。只要湊齊所有百事球星的名字,就可參加百事世界盃之旅的抽獎活動,獲得球星揹包,隨聲聽,更克赴日韓觀看世界盃。還不趕快行動!” 你關上電視,心想:假設有n個不同的球星名字,每個名字出現的概率相同,平均需要買幾瓶飲料才能湊齊

Python學習十一

Python基礎知識(10):函式(Ⅱ) 一、全域性變數和區域性變數 區域性變數:在函式內定義的變數,在函式內使用 全域性變數:在函式外定義的變數,在程式任何地方都可以使用 1、全域性變數與區域性變數同名 這時函式內部只調用區域性變數,如果要呼叫全域性變數需要在函式內加一句“global 同名變數”

Python學習十二

Python基礎知識(11):高階特性 一、分片(切片)   通過索引來獲取一定範圍內的元素 #字串 s="Alice" s[0:4:2] 結果: 'Ai' #列表 l=[1,2,3,4,5,6] l[0:2] 結果: [1, 2] #元組 t=(1,2,3,"a","b","c"

Python學習十七

Python基礎知識(16):面向物件程式設計(Ⅰ) 類和例項 類是抽象的模板 例項是根據類創建出來的一個個具體的物件,每個物件都擁有相同的方法,但各自的資料可能不同。 類可以在建立例項的時候,把一些我們認為必須繫結的屬性強制填寫進去 方法就是與例項繫結的函式,和普通函式不同,方法可以直接訪問例項的

Python學習十八

expand red function encode tabs reduce repl nbsp 試圖 Python基礎知識(17):面向對象編程(Ⅱ) 獲取對象信息 在不知道對象信息的情況下,我們想要去獲取對象信息,可以使用以下方法 1、type (1)判斷對象類型 &

Python學習二十

mil 循環 函數 type() 高級編程 裝飾器 pri 綁定 沒有 Python基礎知識(19):面向對象高級編程(Ⅱ) 定制類 形如“__xx__”的變量或函數在Python中是有特殊用途的 1、__str__ 讓打印出來的結果更好看 __str__:面向用戶;__r

Python學習三十三

Python基礎知識(32):網路程式設計(Ⅰ) 網路通訊是兩臺計算機上的兩個程序之間的通訊,而網路程式設計就是如何在程式中實現兩臺計算機的通訊 P協議負責把資料從一臺計算機通過網路傳送到另一臺計算機 TCP協議則是建立在IP協議之上的。TCP協議負責在兩臺計算機之間建立可靠連線,保證資料包按順序到達

我的Unity開始篇—— 自訴

現在的境地:辭職一年、考研失敗、專業技能忘得差不多、身上沒有資金、面臨重新找工作的問題,嗯,沒有女朋友!!! 現在的想法:去上海、找同學、租房子、找工作、不找女朋友!!! 將來的方向:遊戲是大方向,一部分是因為我同學是遊戲策劃,可以一起幹點事情;一部分是不想玩Java了(不知道為什麼);

Android學習第一篇 SurfaceView的原理以及使用場景

為什麼要使用SurfaceView來實現動畫? 因為View的繪圖存在以下缺陷: View缺乏雙緩衝機制 當程式需要更新View上的影象時,程式必須重繪View上顯示的整張圖片 新執行緒無法直接更新View元件 SurfaceView的繪圖機制

LeetCodeC/C++:4. 兩個排序陣列的中位數

PS:不明之處,請君留言,以期共同進步! 1、題目描述 給定兩個大小為 m 和 n 的有序陣列 nums1 和 nums2 。 請找出這兩個有序陣列的中位數。要求演算法的時間複雜度為 O(lo

WebGL十一透視投影

與正射投影不同,透視投影會出近大遠小的效果,與人的視覺效果一直,遊戲中一般都是使用的透視投影。 示例: /** * 透視投影矩陣 * [email protected] * */ var g_vs = ` attribute vec4

多執行緒Task 任務

一、Task(任務)和ThreadPool(執行緒池)不同       原始碼   1、執行緒(Thread)是建立併發工具的底層類,但是在前幾篇文章中我們介紹了Thread的特點,和例項。可以很明顯發現侷限性(返回值不好獲取(必須在一個作用域中)),當我們執行緒執行完之後不能很

Gym 100418J Lucky tickets數位dp

space mat comm sizeof ++ memset 狀態 out rac 題意:給定一個n。求區間[1, n]之間的全部的a的個數。a滿足: a能整除 把a表示自身二進制以後1的個數 思路:題意非常繞.... 數位dp,對於全部可能的1的個數我們

HDU2089 ------不要62數位dp

判斷 tom name pop iostream blank 位置 play show 不要62 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others