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 ...