演算法分析
解題**
**巧妙點
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...