題目大意:
有乙個\(n*m\)的矩陣,矩陣的每個位置上可以放置乙個數。對於第i行,第i行的差異定義為該行的最大數和最小數的差。乙個矩陣的差異,定義為矩陣中每一行差異的最大值。現在給定k個數v[1..k],問:從這k個數中選\(n*m\)個數放入矩陣,能夠得到的矩陣的差異最小值是多少。
n * m <= k <= 100000, n, m <= 1000,0<= v[i] <= 10^9
二分。
就是二分的板子題,先對每個數排序,然後二分矩陣差異最小值,貪心的判斷是否可以選出n個長度為m的連續子段。
#include #define mid ((l + r) >> 1)
using namespace std;
inline long long read()
const int n = 1e5 + 5, inf = 1e9;
int k, n, m, ans;
int a[n], vis[n];
int check(int s)
else
if(tmp == m)
}if(tag == 0 && tmp == m) res ++;
}return res >= n;
}int main()
printf("%d", ans);
fclose(stdin); fclose(stdout);
return 0;
}
題目大意:
給定乙個長度為n的序列v[1..n],現在要將這個序列分成k段(每段都不能為空),定義每一段的權值為該段上的所有數的或和。定義整個序列的權值為每段權值的和。問:這個序列的最大權值為多少。
k <= n <= 2000,1<= v[i] <= 5 *10^5
線性dp。
考場上想出來60分的做法:
\(f[i][j]\)表示前\(i\)個數分成\(j\)段的最大權值,那麼轉移方程就是:\(f[i][j] = max(f[i][j], f[l][j - 1] + or[l + 1][i])\)。
複雜度\(o(n ^ 3)\)。
考慮優化一下,或和從0變到10^6大概需要20次,如果說沒變,我們只需要取沒變的這一段\(f\)值最大的乙個就好了。因為\(or\)隨著長度變小單調不公升,\(f\)隨著長度變大單調不降,所以這一段最後乙個點就是斷點。所以我們可以與處理出斷點在哪,第三層迴圈直接列舉這些斷點就好了。
複雜度\(o(n^2logn)\)。
#include using namespace std;
inline long long read()
const int n = 2005;
int n, k;
long long a[n], aor[n][n], f[n][n];
vector v[n];
int main()
題目大意:
有一棵k+1層的滿二叉樹,那麼該樹有2^k 個葉子節點。給定n個機械人(n=2^k),編號從1—n,編號為i的機械人的權值為v[i]。我們現在要將這n個機械人分別放置在這n個葉子節點上,每個葉子節點放且只能放乙個機械人。葉子節點的權值為該葉子節點上的機械人的權值。非葉子節點的權值定義為該樹中編號最大的機械人的權值。每個非葉子節點除了權值以外,還有乙個魔法值,該點的魔法值為其左右兒子節點的權值的乘積。整棵樹的魔法值定義為非葉子節點的魔法值的和。問:將這n個機械人隨機地放在這n個葉子節點上,樹的魔法值的期望為多少。
假設答案為乙個不可約分數p/q,則輸出在模1e9+7意義下的p* (q^-1)模1e9+7的值。k <= 18。
組合數 + 推式子
我們假設當先要合併的點高度為d,左子樹權值為x,右子樹權值為y,x > y;
那麼貢獻是這個:\(c(y - 1, 2^d - 1) * c(x - 2 ^ d - 1, 2^d - 1) * v[x] * v[y] * (n - 2^)! * 2 * 2^ * 2^d! * 2^d!\)。
解釋一下:
高度為d的二叉樹節點的子樹中有\(2 ^ d\)個節點,要從比\(y\)小的數裡面選出\(2^d - 1\)個數,順序不同方案也不同,所以是:\(c(y - 1, 2 ^ d - 1) * 2 ^ d!\)。
除去\(y\)的子樹中的節點後,要從比\(x\)小的數裡面選出\(2^d - 1\)個數,順序不同方案也不同,所以是:\(c(x - 2^d - 1, 2 ^ d - 1) * 2 ^ d!\)。
除去\(x, y\)的所有節點後,剩下的數隨便排,所以是:\((n - 2 ^ d - 2^d)! = (n - 2^)!\)。
\(x, y\)的順序可以交換,所以再乘2。
當前高度為d,那麼層數就是\(k - d\)層,二叉樹這一層會有\(2 ^ \)個節點,都可以在這上面合併,所以再乘\(2 ^ \)。
最後再乘上\(x, y\)的權值\(v[x], v[y]\)。
複雜度\(o(kn ^ 2)\)。
可以字尾和優化一下,首先原式子可以寫成:
\(\displaystyle \sum_ \sum_ \sum_ * a(y - 1, 2^d - 1) * a(x - 2^d - 2, 2^d - 1) * (n - 2^)! * 2^\)。
還可以寫成:
\(\displaystyle \sum_ (n - 2^)! * 2^ \sum_ a(y - 1, 2^d - 1) \sum_ a(x - 2^d - 2, 2^d - 1)\)
預處理出後面那兩坨sigema的字尾和就好了,複雜度\(o(kn)\)。
#include #define ls(o) (o << 1)
#define rs(o) (o << 1 | 1)
#define mid ((l + r) >> 1)
using namespace std;
inline long long read()
const int n = 3e5 + 5, mod = 1e9 + 7;
int k, n;
int ans, a[n];
long long fac[n], inv[n], bit[n], sum[n];
void make_pre()
int c(int x, int y)
int main()
printf("%d", 1ll * ans * inv[n] % mod);
fclose(stdin); fclose(stdout);
return 0;
}
10 9 下午 考試
t1 f i 表示不和法數大於i個的數量 f i c n ic 首先n m k n 先不考慮 用擋板法易知 ans c 即給m個果子中間再加上n 1個擋板的位置,在選n 1個 那考慮必須放乙個的情況,只要預先把m n,相當於每個籃子先放乙個 那考慮不合法數 i個,只需要預先給i個放k個,那這i個一定...
10 30 下午考試
p76 年?月?日?題目名稱 他 她 它 名稱 he she it 輸入 he.in she.in it.in 輸出 he.out she.out it.out 每個測試點時限 1 秒 1 秒 1 秒 記憶體限制 512mb 512mb 512mb 測試點數目 10 10 10 每個測試點分值 10...
4 27 下午 閱讀
預設進入系統,我們會看到這樣的字元 root localhost 其中 代表當前是 root 使用者登入,如果是 表示當前為普通使用者。我們了解linux由很多目錄檔案構成,那我們來學習第乙個 linux 命令 cd命令,cd home 解析 進入 home 目錄cd root 進入 root 目錄...