牛客練習賽1 C 圈圈題解

2021-10-12 07:16:52 字數 2709 閱讀 8294

演算法分析

解題**

**巧妙點

shy有乙個佇列a[1], a[2],…,a[n]。現在我們不停地把頭上的元素放到尾巴上。在這過程中我們會得到n個不同的佇列,每個佇列都是a[k],a[k+1],…,a[n],a[1],…,a[k-1]的形式。在這些佇列中,我們可以找到字典序最小的。

shy無聊的時候會給佇列的每個元素加一玩。但是為了使得遊戲不這麼無聊,shy加一以後會給每個元素模m,這樣子字典序最小的序列就會變了,生活就變得有趣。

很顯然這樣子加m次以後,序列會變成原來的樣子。所以現在shy想知道,在他沒有加一前,加一時,加二時,….,加m-1時字典序最小的序列的第k(和上面的k沒有關係)個元素分別是幾。

第一行三個整數n,m,k表示序列長度,取模的數和要求的序列的第幾個元素。

接下來一行n個整數表示初始序列。

m個整數表示答案。

5 6 3

1 2 1 2 3

123

550

對於30%的資料,1≤n,m≤100;

對於100%的資料,1≤n,m≤50000, 1≤k≤n, 0≤a[i]這道題第一眼看上去,就動不了手,想了半天,看了題解才明了

這道題目的關鍵點在於:只有某乙個數字出現了對於m的溢位時,序列才會發生改變

但怎麼對初始序列和改變以後的序列進行重新組合排序呢?

這裡就用到了**二分**,二分去尋找lcp(最長公共字首),並且比較lcp後的那個數字,如果數字更小,那麼這個數字就應該放在隊首。

這個解題思路成立的關鍵點在於**不停地把頭上的元素放到尾巴上** ,因此可以把序列看作乙個迴圈佇列。

#include

#include

using

namespace std;

#define int long long

const

int n=20;

const

int base=

1e9+7;

int n,m,k,l,r,ans,mid,a[n]

,ha[n]

,p[n]

;vector<

int>v[n]

;intbj(

int x,

int y,

int add)

//l實際上是 以x為起點,和以y為起點相等的最大長度

//如果l==n,就意味著x和y實際上是相同的位置,得到的長度為n的序列

if(l == n)

return x;

//因為以x為起點,和以y為起點的序列相同的,那麼就比較這兩個串後的那個不同的數字,

//將小的字元的下標返回,作為序列的排頭元素

//(以x為起點和以y為起點的長度為l的串是等價的,因此可以將這之後的更小的字典的數字替換到第乙個位置)if(

(a[x + l]

+ add)

% m <=

(a[y + l]

+ add)

% m)

return x;

else

}signed

main()

//一維字串hash

for(

int i =

1; i <= n + n; i++

) ha[i]

= ha[i -1]

* base + a[i]

; p[0]

=1;for

(int i =

1; i <= n + n; i++

) p[i]

= p[i-1]

* base;

//一維字串hash

//反覆尋找可以作為排頭的數字的下標

ans =1;

for(

int i =

2; i <= n; i++

) ans =

bj(ans, i,0)

;printf

("%lld\n"

,a[ans + k -1]

);for(

int i =

1; i < m; i++

)printf

("%lld\n"

,(a[ans + k -1]

+ i)

% m);}

return0;

}

for

(int i =

1; i <= n; i++

)

1、vector陣列v在輸入時就預先存入在加i時,會發生對m溢位的數字

2、在a陣列中多存一輪序列,就不用複雜的去考慮頭尾移動的複雜情況(因為可以將頭元素移動到尾部)

if

(v[i]

.size()

)

因為,一次加1的操作可能導致多個數同時發生對m溢位。

所以,要在此次 發生對m溢位的數 中,通過比較去尋找真正的排頭元素

牛客練習賽1

a矩陣 題意 給出乙個n m的矩陣。讓你從中發現乙個最大的正方形。使得這樣子的正方形在矩陣 現了至少兩次。輸出最大正方形的邊長。n 500,m 500 題解 考慮暴力 列舉每個矩陣為 n 3 然後判斷兩個矩陣是否相等 n 2 顯然複雜度 如果將矩陣進行hash 然後o 1 判斷兩個矩陣是否相等,那麼...

牛客練習賽22題解

簡單瞎搞題 不會用bitset,所以沒做出來。實際上還是比較簡單的。include using namespace std bitset 1000005 dp 2 int main cout 2 count 簡單資料結構1 這裡要運用拓展尤拉定理。ab modp ab p b p p 0 modp ...

題解 牛客練習賽51

字首a的數量,字尾c的數量,遇到b就計算一次答案。includeusing namespace std typedef long long ll const int n 1e5 100 char s n int cnt n int main int tmp 0 for int i 1 i n i p...