題目大意:
給定乙個排列,為這個排列字典序的下乙個排列是啥?\(n <= 1e5\).(不能用next_permutation.)
從後往前找第乙個\(x_i < x_\)的數,這個數\(i\)之後的數是單調遞減的.也就是說這個數後面的已經是極大的了,不能通過改變順序是後面這幾個數更大,所以我們只能增大\(i\)位置上的這個數,在後面的數中找乙個比它大的最小的數,讓他倆交換位置,剩下沒選過的數就從小到大排一遍序就好了.
#include using namespace std;
inline long long read()
const int n = 1e5 + 5;
int n, p[n], vis[n];
int main()
} if(pos == 0) for(int i = 1;i <= n; i++) printf("%d ", i);
else
if(!tag)
for(int i = 1;i <= pos; i++) printf("%d ", p[i]);
for(int i = 1;i <= n; i++) if(vis[i]) printf("%d ", i); }
fclose(stdin); fclose(stdout);
return 0;
}
題目大意:給定一棵樹,再給出所有的葉子結點經過的順序,然後從根節點1開始走,每條邊最多走兩次,最後回到根節點,問是否可以走出一條路徑滿足給定的經過葉子結點的順序.不能的話輸出-1,否則輸出這條路徑.\(n <= 1e5\).
\(lca\) 樹上問題.
我們發現直接按題意模擬是可以通過時間複雜度的,因為每條邊最多走兩次,所以最多走\(2n - 2\)條邊.所以我們按給定的葉子結點的順序求出相鄰兩個葉子結點的\(lca\).然後暴力條父親就好了,記得記錄一下邊的經過次數.
#include using namespace std;
inline long long read()
const int n = 1e5 + 5;
int n, cnt, num;
int id[n], dep[n], fa[n][21], head[n], tmp_ans[n * 10], ans[n * 10], in_edge[n];
struct edge e[n << 1];
void add(int x, int y)
void get_tree(int x, int fa)
if(!tag) num ++;
}void make_fa()
int lca(int x, int y)
int main()
get_tree(1, 0); make_fa();
int last = 1; tot = 0;
for(int i = 1, x, lca;i <= num + 1; i++) }
for(int i = 2;i <= cnt; i++) ans[++ tot] = tmp_ans[i];
ans[++ tot] = lca;
tmp = x; cnt = 0;
while(tmp != lca) }
for(int i = cnt;i >= 1; i--) ans[++ tot] = tmp_ans[i];
last = x;
} for(int i = 1;i <= tot; i++) printf("%d ", ans[i]);
fclose(stdin); fclose(stdout);
return 0;
}
題目鏈結
題目大意:給定\(n\)數\(a\)和\(n\)個數\(b\),求\(a > b\)的對數 - \(b > a\)的對數恰好等於\(k\)的方案數.\(n <= 2000\),答案對\(1e9 + 9\)取模.保證每個\(a, b\)都不相等.
首先我們可以得到\(a > b\)的對數是\(\frac \).然後我們對\(a, b\)從小到大排序.
\(f[i][j]\)表示前\(i\)個\(a\),欽定有\(j\)對\(a > b\)的方案數,那麼dp轉移方程就是:\(f[i][j] = f[i - 1][j] + f[i - 1][j - 1] * (g[i] - (j - 1))\).
為什麼是欽定不說恰好呢?假設當前所有\(a_i\)都大於\(b\),那麼是無法恰好選出\(j\)對的,因為所有的\(a_i\)都可以與其他的\(b\)形成\(a > b\),欽定的意思是強制選取\(j\)對,其他的不管,這樣之後求\(h[j]\)的時候會乘上\((n - j)!\),求出來的\(h[j]\)才是正確的.
\(g[i]\)表示有多少個\(b\)小於\(a_i\).這個轉移方程的含義就是"第\(i\)個數\(a_i\)沒有形成\(a > b\) + 第\(i\)個數\(a_i\)形成了\(a > b\)並且這個\(b\)前\(j - 1\)對\(a > b\)中沒有出現過 ".
\(h[i]\)表示至少有\(i\)對\(a > b\)的方案數(這裡也可以說是欽定\(i\)對\(a > b\),其他的不管的方案數),那麼可以得到:\(h[i] = f[n][i] * (n - i)!\).剩下\(n - i\)個數隨便排列,可能形成\(1\)到\(n - i\)對新的\(a > b\).(這樣算出的\(h[i]\)是有重複方案的對吧)
\(ans[i]\)表示恰好有\(i\)對\(a > b\)的方案數,我們可以發現它和\(h[i]\)的關係:\(h[i] = \displaystyle \sum_^ c_^ ans[j]\).重新看\(h[i]\)的定義:至少有\(i\)對\(a > b\)的方案數.那麼我們就要把所有\(j >= i\)的\(ans[j]\)統計到\(h[i]\)裡面,並且要算上重複的部分,也就是在乘上\(c_^\)(因為欽定了\(i\)對嘛)..
然後我們把\(ans[i]\)移到一邊:\(ans[i] = h[i] - \displaystyle \sum_^ c_^ ans[j]\).然後倒推就可以了.時間複雜度\(o(n ^ 2)\).
#include using namespace std;
inline long long read()
const int n = 2005, mod = 1e9 + 9;
int n, k, num;
int a[n], b[n], g[n], h[n], fac[n], ans[n], inv[n], f[n][n];
void make_pre()
int c(int n, int m)
int main()
num = (n + k) / 2;
for(int i = 1;i <= n; i++) a[i] = read();
for(int i = 1;i <= n; i++) b[i] = read();
sort(a + 1, a + n + 1); sort(b + 1, b + n + 1);
for(int i = 1;i <= n; i++)
for(int j = 1;j <= n; j++)
if(a[i] > b[j]) g[i] ++;
else break;
for(int i = 0;i <= n; i++) f[i][0] = 1;
for(int i = 1;i <= n; i++)
for(int i = 0;i <= n; i++)
h[i] = 1ll * f[n][i] * fac[n - i] % mod;
for(int i = n;i >= num; i--)
printf("%d", ans[num]);
return 0;
}
考試總結 CQOI2017 考試總結
再奮鬥一年,爭取ak noip2016 cqoi2017 這是去年我立的flag。看考場,電腦挺快,而且配置和評測機一樣,可以放心的在自己的電腦上卡常測試啦,好評。碼了一道fft的題,沒網只好拷著回家交,鍵盤蜜汁小,enter佔據了兩行,旁邊還有關機按鈕。座位安排奧妙重重,和巴蜀dyf大神坐在一起。...
MBA考試總結
終於考完了 mba入學統考,兩年來參加了兩次,感覺還是挺辛苦和有壓力的。第一年沒有通過是因為之前了解太遲,大概準備了 20天左右,最後還是功成垂敗。09年其實也一直沒有心情複習的,逼到最後的 20天,狠了一把勁,還是狠狠的複習了幾天,貌似今年應該可以通過了。總結經驗如下 1 如果你決定去做一件事,請...
2016 7 14考試總結。
今天的考試,總的來說不難,但是考得很差,簡直 從中暴露出對知識的掌握不牢固,練習不夠等問題。1.求 方程x1 2x2 nxn m的所有非負整數解 x1,x2,xn 的個數。這個題目在加上取餘運算後就是乙個貨幣系統的問題。也就是揹包。難以接受自己連這是個揹包問題都沒看出來。3 2.其實邪狼王的貪婪也很...