2021牛客寒假演算法基礎集訓營1 解題補題報告

2022-04-30 19:03:10 字數 4012 閱讀 8830

官方題解

記 \(dp(i)\) 為長度為 \(i\) 且包含 \(us\) 的字串的總數量,接下來我們考慮遞推關係:

如果前 \(i-1\) 項中已經含有 \(us\),那麼第 \(i\) 項什麼都行,總計 \(26*dp(i-1)\)

如果前 \(i-1\) 項裡面只有 \(u\),那麼第 \(i\) 項必須為 \(s\)。我們考慮下前 \(i-1\) 項裡面只有 \(u\) 沒有 \(s\) 的情況:

總計可以構成 \(26^\) 種字串,其中完全沒有 \(u\) 的有 \(25^\) 種,有 \(u\) 又有 \(s\) 的一共 \(dp(i-1)\) 種,所以總計 \(26^ - 25^ - dp(i-1)\) 種。

綜上,我們可以得到 \(dp\) 方程:\(dp(i) = 25 *dp(i-1) + 26^-25^\),最後的答案就是 \(\displaystyle\sum\limits_^dp(i)\)

#includeusing namespace std;

#define ll long long

const int n = 1000010;

const ll mod = 1e9 + 7;

int n;

ll dp[n], pow_25[n], pow_26[n];

int main()

理論上,這個公式是可以推出來的(也是我比賽時的思路),但是這玩意估計太難,到現在還沒看到有啥正確的組合公式

如果不限制的話,我們顯然可以找出一種構造方式:一開始給乙個左括號,然後跟著一堆右括號,或者反過來(例如 \(())))))))))\) 或者 \(((((((((((((((()\)),奈何題目對輸出有限制,沒辦法

雖然有限制,沒法直接用上面這方法,但是我們如果推廣一下:\((()))))))))))\),如果一開始給的是兩個呢?三個呢?

這種方法只能對應某個數的倍數的情況,但是我們再換乙個思路呢?如果在這後面再加上類似的東西呢?例如這樣:\((()))())\)

顯然,每增加乙個右括號,括號串中增加的合法括號對的數量為該右括號左邊的左括號數量之和。

根據上面的鋪墊,我們不難找出一種構造方式,將 \(k\) 表示成 \(ax+by\) 的形式,先給 \(a\) 個左括號,然後給 \(x\) 個右括號,然後 \(b\) 個左括號,再跟著 \(y\) 個右括號,最後能夠構成 \(k\) 個括號對,並且總長度為 \(a+b+x+y\) 。

字串最大長度為 \(100000\),理論上能構造出來的最多的括號對數量為 \(49999^2\),大於 \(k\) 的最大值,所以這種構造是正確的。

另外,\(k=0\) 的時候記得特判下,有可能出 \(bug\)。

#includeusing namespace std;

#define ll long long

ll k;

void output(ll a, ll b)

}int main()

}return 0;

}

最低顯然為 \(0\) (從頭錯到位),最高的話要看每一題:兩人相同則加 \(2\)(全對),不同則加 \(1\) (肯定錯乙個)。

#includeusing namespace std;

const int n = 110;

int n, a[n], b[n];

int main()

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

int max_score = 0;

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

}cout告辭

找規律這種東西全憑靈性,沒啥好總結的,想看的自己去看官方題解

我整個不一樣的吧:尤拉降冪

(感謝 dalao小粉兔的題解)簡單來說就是:

有了這玩意,我們便可以將這個 \(nt\) 數學式子化簡,直至變成乙個我們可以肉眼推出的形式。

簡單來說,分成以下幾類(過程略,心累):

#includeusing namespace std;

const int n = 100010;

char str_a[n], str_n[n];

int read(char *s, int mod)

int quickpow(int a, int b, int mod)

int main()

else printf("%d", quickpow(a_10, quickpow(a_4, a_2 + 2, 4) + 4, 10));

return 0;

}

\(k \leq \frac\) 真的關鍵,不然這題沒法寫了都(雖然有這個條件的題目我都沒寫出來)

有一種(並非那麼)顯然的排列方式:所有偶數排在一起,所有奇數排在一起,成功構成的對的數量就在 \(k\) 附近。如果缺,可以讓奇偶數的連線點是 \(6\) 和 \(3\);多的話,把左邊偶數排列拆掉一些就好了。

另外,對於 \(n \leq 5\) 的情況(這時候沒有 \(6\) 可以拿來和 \(3\) 拼接),直接特判打表吧。

思路是這樣的,但是不代表**很好寫(逃)

#includeusing namespace std;

int n, k;

int main()

if (n <= 3) printf("-1");

else if (n == 4)

else if (n == 5)

if (n < 6) return 0;

//solve

if (2 * k == n || 2 * k + 1 == n)

bool vis[100010];

memset(vis, 0 , sizeof(vis));

for (int i = 1, cnt = 1; 2 * i <= n && cnt <= k + 1; ++i, ++cnt)

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

if (!vis[i]) printf("%d ", i);

return 0;

}

這個篩子,篩掉的是所有只有一種質因子的數,剩下來的數都有一種以上的質因子。

求他們的 \(lcm\),我們需要借助算數基本定理來計算:

對於其中任意剩下來的數,都可以表示成這樣:\(p_1^p_2^p_3^......p_n^\) 的形式(\(p_i\) 是質數)

對應的,他們的 \(lcm\) 就是 \(p_1^}p_2^}p_3^}......p_n^}\)

顯然,\(p1=2\),\(\max a_1\) 的值,相當於使得\(3*2^k \leq n\) 的情況下的 \(k\) 的最大值,即 \(\max a_1 = \lfloor log_2^} \rfloor\),對 \(lcm\) 的貢獻就是 \(2^\)

對於 \(p_i(i \geq 2)\),\(\max a_i= \lfloor log_^} \rfloor\),對 \(lcm\) 的貢獻就是 \(p_i^\)

那麼很顯然,我們的任務就是篩出不大於 \(n\) 的所有質數,然後一一累計貢獻就好了。(看看這 \(n\) 的規模,線性篩我都覺得過不了)

#include using namespace std;

#define ll long long

const int n = 80000010;

const ll mod = 1e9 + 7;

int n, num[n], prim[5000060];

int pn = 0;

void table()

}}int main()

ll res = 1;

for (int i = 1; prim[i] <= n / 2; i++)

ll temp2 = 1;

while (temp2 * 2 <= n / 3)

temp2 *= 2;

res = res * temp2 % mod;

cout << res;

return 0;

}

2021牛客寒假演算法基礎集訓營3

三場牛客下來覺得自己越來越不在狀態,思路不清晰,一下手就是bug,每調完一題刷下榜都被甩開十里地,罰時慘不忍睹 傳送門 簽到 include using namespace std typedef long long ll const ll inf 0x3f3f3f3f const ll mod 1...

2021牛客寒假演算法基礎集訓營1

題目描述 請你構造乙個非空的括號字串,包含正好 k 個不同合法括號對。所謂括號字串,是指由 和 這兩種字元構成的字串。要求構造的字串長度不超過100000。輸入描述 乙個整數 k。乙個整數 kk。0 k 1e9 輸出描述 乙個僅包含左右括號字串,其中有 kk 個合法的括號對。如果有多種構造方法,輸出...

2021牛客寒假演算法基礎集訓營6

思路 k1排k2前面滿足 k1.a k2.ax k2.b k1.b k1.ax k1.b k2.b k2.ak1.b k2.b k1.a k2.a k1.b include define ull unsigned long long define ll long long const int inf...