訓練賽 詠歎

2021-08-02 04:35:34 字數 1881 閱讀 9108

安師大附中訓練題目

給定乙個1到n的排列a,對其進行氣泡排序:

counter=0

while a不是公升序的

counter=counter+1

for i=1

to n-1

if a[i]>a[i+1]

then swap(a[i],a[i+1])

endifend

forend

while

那麼經過幾輪排序之後a序列會變成公升序呢?(即counter變數的值)

輸入n,s,b,c,d五個整數,資料按以下方式生成:

for i=1

to n

a[i]=i

s=(s*b+c) mod d

swap(a[i],a[(s mod i)+1])

endfor

一行,乙個整數,表示氣泡排序進行的輪數,即counter變數的值.

對於30%的資料,1≤

n≤103

對於50%的資料,1≤

n≤105

對於70%的資料,1≤

n≤106

對於100%的資料,1≤

n≤3×

107,0

≤s,b

,c109+7

時間限制:2s

空間限制:233m (原題如此)

按照氣泡排序進行模擬,o(

n2) ,30分.

我拿到題的第一反應是打表找規律,然而好像沒有發現什麼明顯的規律。之後我就開始嘗試尋找各種結論,然而都有反例。這個時候我意識到,解決這種問題必須要尋找出每次操作都遵循的不變數,或者是通行的規則。

首先我想到了逆序對,然而每一輪消去的逆序對數量是變化的,我們沒有辦法通過逆序對來求得最終的輪數。

然後我開始注意波浪形,關注波峰波谷以及上公升鏈下降鏈,沒有找到出路。

我開始關注到氣泡排序的逆操作,考慮在乙個公升序序列中交換一些數,會給答案帶來怎樣的貢獻。也沒有發現有用的性質。

幾經磨難,我還是發現了正解。我們注意到,對於乙個數而言,如果它的左側存在比它大的數,那麼這些比它大的數肯定會越過它,到達右側的區域。而且每一輪操作左側有且僅有乙個比它大的數越過它。我們不妨將第i個數的左側比a[i]大的數的個數記作f[i],那麼最終的輪數一定滿足co

unte

r≥ma

xf[i

](1≤

i≤n)

這個時候,我們猜想這個式子是取等號的。的確,對拍結果顯示它的確是取的等號。為什麼?自行意會,我說不清楚.

至此我們可以用樹狀陣列維護左側比a[i]小的數的個數,可得70分.

怎麼優化呢?

對於a[i]=1而言,f[i]=i-a[i];

對於a[i]=2而言,如果1在2左側,那麼f[i]=i-a[i]成立;如果1在2右側,那麼f[i]一定不是最大值,因為1處的f值肯定大於f[i];以此類推,對於a[i]=k而言,如果1~k-1都在k左側,則f[i]=i-a[i];否則,f[i]必定不是最大值。於是co

unte

r=ma

x(i−

a[i]

) 至此我們得到了o(n)演算法。要想拿滿100分,必須要常數足夠小;實際評測中,用long long的,取模較多的都只有70分.

#include

#include

using namespace std;

#define maxn 30000500

int s,b,c,d,a[maxn],n;

int main()

int ans=0;

for(int i=1;i<=n;i++)

printf("%d\n",ans);

return

0;}

**非常短!

訓練 9 13 訓練賽

a.hdu 6230 乙個合法的子串 s 3n 2 滿足條件即1 2n 1 為以n為回文中心的回文串,n 3n 2為以2n 1為中心的回文串。故我們可以通過尋找回文中心對,來判斷相應合法子串的個數。利用manacher求出每個位置的最長回文半徑,則若i,j滿足條件 i j 則應有 p i geqsl...

訓練賽 浣熊

從前有乙隻可愛的小浣熊居住在美麗的森林裡。他聽說小鸚鵡要旅行到另乙隻鸚鵡家做客,也想邀請朋友們來自己家。為此,小浣熊想建一棟新房子。他找到了一塊比較大的平地,不過這塊地上還是有一些地方不能建屋。不妨把這塊空地看作是由n行m列等大小的正方形格仔組成。現在,小熊已經把不能建房子的地方都標記了出來,他想找...

訓練賽補題

codeforces 1041b 思考 1 求最大公約數的時候除法比減法要快,以後能用除法去處理大數就不要用劍法去處理大數 codeforces 1041c 題意 其實就是給定了n個數,問間隔最少d,那麼這樣最少是幾組,並且哪個是哪一組的 思路 就是直接進行比較,先進行按照數值進行從小到大排序,如果...