牛客練習賽1

2021-10-10 09:51:14 字數 3644 閱讀 6888

a矩陣

題意

給出乙個n * m的矩陣。讓你從中發現乙個最大的正方形。使得這樣子的正方形在矩陣**現了至少兩次。輸出最大正方形的邊長。\(n <= 500, m <= 500\)

題解:考慮暴力

列舉每個矩陣為 \(n ^ 3\)然後判斷兩個矩陣是否相等 \(n ^ 2\)顯然複雜度**, 如果將矩陣進行hash 然後o(1)判斷兩個矩陣是否相等,那麼最後的複雜度為 \(n ^ 3\) , 好像還是不行。

這個時候就要考慮如何優化了。

仔細想一下矩陣**現兩個個長度為\(x\)的且相同的正方形, 那麼一定存在兩個長度為\(x - 1\)相同的正方形, 同樣一會出現長度為 \(x - 2 ………… , 1\)的正方形, 有了這個結論, 那麼可以直接二分長度了, 如果存在就向右移動, 否則向左移動。

**:

#includeusing namespace std;

const int n = 1000;

const int maxn = 1e3+5;

const int maxn = 1e3+5;

typedef unsigned long long ull;

ull p = 13331,p1 = 233333;

ull hasha[maxn][maxn];

ull hasha1[maxn][maxn];

ull powp[maxn];

ull powp1[maxn];

char str[n][n];

void init()

vis[cnt]++;

} else }}

return false;

}int main()

init();

make_hash(n, m);

int l = 0, r = min(n, m), ans;

while (l <= r) else

}cout << ans + 1 << endl;

}

b樹

題意:

shy有一顆樹,樹有n個結點。有k種不同顏色的染料給樹染色。乙個染色方案是合法的,當且僅當對於所有相同顏色的點對(x,y),x到y的路徑上的所有點的顏色都要與x和y相同。請統計方案數。

題解:考慮組合數學

首先肯定肯定知道, 將樹劃分成幾個聯通快, 然後每個聯通快塗乙個顏色。

假設當前聯通快的個數為 \(x\) 顏色的數量為 \(n\) 那麼當前的答案就是乙個全排列, \(ans = n * (n - 1) * (n - 2) * ...... (n - x + 1)\)

那麼怎麼求乙個樹可以分成多少個連通塊呢?這個問題可以用dp去求, 但是我覺得比較麻煩, 有個數學方法可以直接求。

對於一顆樹, 聯通快的個數不就是將樹刪邊, 樹有 \(n - 1\)條邊, 刪一條邊那麼將出現兩個連通塊, 刪兩條邊就會出現三個聯通快, 同時刪一條邊的方案數為 \(c_^\) , 刪兩條邊的方案樹為 \(c_ ^\) 以此類推。

**:

#includeusing namespace std;

const int n = 1e4;

typedef long long ll;

const long long mod = 1e9+7;

long long fac[2000006]; // 階乘表

long long qpow(long long x, long long n)

long long inv(long long a)

void solve()

}long long comb(long long n, long long k)

ll n, k;

ll work(ll x)

return res;

}int main()

cout << ans << endl;

}

c 圈圈

題意:

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 ^ 2\)列舉每乙個長度為n的字串然後在比較大小。

這樣肯定是不行的, 那有更優的方案嗎。

考慮到每個字典序直接的比較一定是前面的元素的都是相等, 然後當前位的元素比較小那麼就不需要在繼續比較了

是不是可以找到乙個最長相等的字首, 然後在比較下一位。

先選乙個起始串, 然後通過二分+雜湊找到與起始串最長的字首, 然後比較下一位, 如果比起始串小, 那麼在更新起始串, 繼續列舉下乙個字串, 通過 hash+ 二分進行查詢, 然後在繼續……

這樣的複雜度位 列舉為 \(o(n)\) 判斷每個字典序的大小為 \(log(n)\)所以總時間複雜度為\(o(n * log(n))\)

如果每次都給所以數加1 在模上 m, 總共操作m次, 每次都這麼找的話時間複雜度不就是為 \(o(n * m * log(n))\)

很顯然這樣肯定過不了, 仔細想一下每次給所有數加1 然後在取模, 是不是只有 變為0的數才對答案產生貢獻啊

然後記錄有那幾個數將在加多少次變為0, 然後在用上面的方案找出字典序的最小的, 因為只操作m次, 所以每個數隻會有一次變為0, 所以每個數隻進行一次比較,最後的複雜度為\(o(m * log(n))\)

**:

#includeusing namespace std;

const int n = 5e5 + 7;

typedef long long ll;

const ll mod = 1e9 + 7;

int n, m, k;

ll fn[n], hash[n];

ll a[n];

void init()

}ll get_hash(int l, int r)

int work(int x, int y, int v) else

}if ((a[x + ans] + v) % m < (a[y + ans] + v) % m)

return y;

}vectorg[n];

int main()

n += n;

init();

int ans = 1;

for (int i = 2; i <= n / 2; i++)

printf("%lld\n", a[ans + k - 1]);

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

}printf("%lld\n", (a[ans + k - 1] + i) % m);

}}

牛客練習賽9

時間限制 c c 1秒,其他語言2秒 空間限制 c c 32768k,其他語言65536k 64bit io format lld 珂朵莉想每天都給威廉送禮物,於是她準備了n個自己的本子 她想送最多的天數,使得每天至少送乙個本子,但是相鄰兩天送的本子個數不能相同 珂朵莉最多送幾天禮物呢 第一行乙個整...

牛客練習賽15

時間限制 c c 2秒,其他語言4秒 空間限制 c c 262144k,其他語言524288k 64bit io format lld 第一次期中考終於結束啦!沃老師是個語文老師,他在評學生的作文成績時,給每位學生的分數都是乙個小於10的非負小數。amy 8.99999999999999999999...

牛客練習賽5

給你n個正整數,n 5,每個正整數大小不超過1000,最初su m 0 sum 0 每次可將su m sum 按順序加上陣列中的數,加完之後可以對sum的數字進行全排列,求最終能達到的最大值。由於n只有5,所以按照題意模擬dfs實現就可以了,注意最後一組也可以按數字進行全排列。d題 include ...