安師大附中訓練題目
給定乙個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,那麼這樣最少是幾組,並且哪個是哪一組的 思路 就是直接進行比較,先進行按照數值進行從小到大排序,如果...