暫時不想寫太詳細的題解了,就先只放我的程式碼好了,以後如果想寫了的話再寫寫具體想法吧
今年沒參加正賽,這兩天忽然來了點興趣所以做了做這套題,順便造了些資料放本校OJ上當練習題用
感覺難度和去年比算是持平吧,最難的題比去年要簡單了些的
解法可能不一定是對的,但時間和空間限制我自己都有測試過,問題不大
如有錯誤請指出謝謝~
合法密碼
#include<bits/stdc++.h>
using namespace std;
int ans = 0;
string s = "kfdhtshmrw4nxg#f44ehlbn33ccto#mwfn2waebry#3qd1ubwyhcyuavuajb#vyecsycuzsmwp31ipzah#catatja3kaqbcss2th";
bool check(string s)
{
bool f = false, g = false;
for(char c : s)
{
if(isalpha(c))
continue;
if(isdigit(c))
{
f = true;
continue;
}
g = true;
}
return f && g;
}
int main()
{
for(int i = 0; i < s.size(); i++)
{
for(int j = i + 7; j < s.size() && j - i + 1 <= 16; j++)
{
if(check(s.substr(i, j - i + 1)))
ans++;
}
}
cout << ans;
return 0;
}
選數機率
#include<bits/stdc++.h>
using namespace std;
int gcd(int x, int y)
{
return y == 0 ? x : gcd(y, x % y);
}
bool check(int a, int b, int c)
{
int c2 = (a + b + c) * (a + b + c - 1) / 2;
int x, y, z;
x = a * b, y = c2;
z = gcd(x, y);
if(x / z != 517 || y / z != 2091)
return false;
x = b * c, y = c2;
z = gcd(x, y);
if(x / z != 2632 || y / z != 10455)
return false;
x = a * c, y = c2;
z = gcd(x, y);
if(x / z != 308 || y / z != 2091)
return false;
return true;
}
int main()
{
for(int a = 1; a <= 100; a++)
for(int b = 1; b <= 100; b++)
for(int c = 1; c <= 100; c++)
{
if(check(a, b, c))
cout << a << "," << b << "," << c;
}
return 0;
}
螞蟻開會
#include<bits/stdc++.h>
using namespace std;
int n;
int ux[505], uy[505], vx[505], vy[505];
int ans = 0;
map<int, int> mp;
inline int _hash(int x, int y)
{
return x * 13331 + y;
}
void add(int x, int y)
{
if(++mp[_hash(x, y)] == 2)
ans++;
}
int gcd(int x, int y)
{
return y == 0 ? x : gcd(y, x % y);
}
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> ux[i] >> uy[i] >> vx[i] >> vy[i];
if(ux[i] != vx[i])
{
if(ux[i] > vx[i])
{
swap(ux[i], vx[i]);
swap(uy[i], vy[i]);
}
int dx = vx[i] - ux[i], dy = vy[i] - uy[i];
int g = abs(gcd(dx, dy));
dx /= g, dy /= g;
for(int x = ux[i], y = uy[i]; x <= vx[i]; x += dx, y += dy)
add(x, y);
}
else
{
if(uy[i] > vy[i])
swap(uy[i], vy[i]);
for(int x = ux[i], y = uy[i]; y <= vy[i]; y++)
add(x, y);
}
}
cout << ans << "\n";
return 0;
}
立定跳遠
#include<bits/stdc++.h>
using namespace std;
int n, m;
int a[100005], b[100005];
bool check(int d)
{
int t = m + 1; // 把2L看作多一個跳板
for(int i = 1; i <= n; i++)
{
t -= (b[i] - 1) / d;
if(t < 0)
return false;
}
return true;
}
int main()
{
cin >> n >> m;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
b[i] = a[i] - a[i - 1];
}
sort(b + 1, b + n + 1);
int l = 1, r = 1e8;
while(l <= r)
{
int mid = l + r >> 1;
if(check(mid))
r = mid - 1;
else
l = mid + 1;
}
cout << l;
return 0;
}
最小字串
#include<bits/stdc++.h>
using namespace std;
char s[100005], t[100005];
int main()
{
int n, m;
cin >> n >> m;
cin >> (s + 1) >> (t + 1);
sort(t + 1, t + m + 1);
int p = 1, q = 1;
while(p <= n && q <= m)
{
if(s[p] <= t[q])
cout << s[p++];
else
cout << t[q++];
}
while(p <= n)
cout << s[p++];
while(q <= m)
cout << t[q++];
cout << "\n";
return 0;
}
數位翻轉
#include<bits/stdc++.h>
using namespace std;
long long dp[1005][1005][2];
int a[1005], b[1005];
int f(int x)
{
int r = 0;
while(x)
{
r = (r << 1) | (x & 1);
x >>= 1;
}
return r;
}
int main()
{
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
b[i] = f(a[i]);
}
for(int i = 1; i <= n; i++)
{
dp[i][0][0] = dp[i - 1][0][0] + a[i];
for(int j = 1; j <= m; j++)
{
dp[i][j][0] = max(dp[i - 1][j][0] + a[i], dp[i - 1][j][1] + a[i]);
dp[i][j][1] = max(dp[i - 1][j][1] + b[i], dp[i - 1][j - 1][0] + b[i]);
}
}
cout << max(dp[n][m][0], dp[n][m][1]) << "\n";
return 0;
}
數星星
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 1e9 + 7;
int n, d[100005], L, R;
ll fac[100005], inv[100005];
ll f[100005];
ll qpow(ll a, ll n)
{
ll r = 1;
while(n)
{
if(n & 1)
r = r * a % mod;
a = a * a % mod;
n >>= 1;
}
return r;
}
ll getC(int n, int m)
{
if(n < 0 | m < 0 || n < m)
return 0;
return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
int main()
{
cin >> n;
for(int i = 1; i < n; i++)
{
int a, b;
cin >> a >> b;
d[a]++;
d[b]++;
}
cin >> L >> R;
fac[0] = 1;
for(int i = 1; i <= n; i++)
fac[i] = fac[i - 1] * i % mod;
inv[n] = qpow(fac[n], mod - 2);
for(int i = n - 1; i >= 0; i--)
inv[i] = inv[i + 1] * (i + 1) % mod;
ll ans = 0;
if(L == 1 && L <= R)
{
ans += n;
L++;
}
if(L == 2 && L <= R) // 這個特判也許是易錯點?兩點組成的圖不能重複計算
{
ans += n - 1;
L++;
}
for(int i = L - 1; i <= n; i++)
{
// for(int j = L; j <= R; j++)
// f[i] = (f[i] + getC(i, j - 1)) % mod;
f[i] = ((f[i - 1] * 2 - getC(i - 1, L - 1) - getC(i - 1, R - 1) + getC(i, L - 1)) % mod + mod) % mod; // 楊輝三角公式遞推
}
// f[i] 表示菊花圖中間點的度數為 i 時的方案總數
for(int i = 1; i <= n; i++)
ans = (ans + f[d[i]]) % mod;
cout << ans << "\n";
return 0;
}
套手鐲
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> pii;
int N, W, H;
int x[1005], y[1005], r[1005];
vector<int> xpool;
int ans;
int tr[1005], maxn;
int lowbit(int x)
{
return x & -x;
}
void update(int p, int v)
{
while(p <= maxn)
{
tr[p] += v;
p += lowbit(p);
}
}
int query(int p)
{
int r = 0;
while(p)
{
r += tr[p];
p -= lowbit(p);
}
return r;
}
void initBIT(int n)
{
maxn = n;
while(n)
tr[n--] = 0;
}
void solve()
{
for(int &L : xpool)
{
int R = L + W;
vector<pii> line;
vector<int> ypool;
for(int i = 1; i <= N; i++)
if(x[i] - r[i] >= L && x[i] + r[i] <= R)
{
line.push_back(pii(y[i] - r[i], y[i] + r[i]));
ypool.push_back(y[i] + r[i]);
}
sort(line.begin(), line.end());
sort(ypool.begin(), ypool.end());
ypool.erase(unique(ypool.begin(), ypool.end()), ypool.end());
initBIT(ypool.size());
for(pii &l : line)
update(lower_bound(ypool.begin(), ypool.end(), l.second) - ypool.begin() + 1, 1);
for(pii &l : line)
{
int p = upper_bound(ypool.begin(), ypool.end(), l.first + H) - ypool.begin();
// if(p == 0)
// continue;
ans = max(ans, query(p));
update(lower_bound(ypool.begin(), ypool.end(), l.second) - ypool.begin() + 1, -1);
}
}
}
int main()
{
cin >> N >> W >> H;
for(int i = 1; i <= N; i++)
{
cin >> x[i] >> y[i] >> r[i];
xpool.push_back(x[i] - r[i]);
}
sort(xpool.begin(), xpool.end());
xpool.erase(unique(xpool.begin(), xpool.end()), xpool.end());
solve();
swap(W, H);
solve();
cout << ans << "\n";
return 0;
}
跳石頭
#include<bits/stdc++.h>
using namespace std;
int n, c[40005];
bitset<40005> bs[40005];
int main()
{
cin >> n;
for(int i = 1; i <= n; i++)
cin >> c[i];
int ans = 0;
for(int i = n; i >= 1; i--)
{
bs[i].set(c[i]);
if(i + c[i] <= n)
bs[i] |= bs[i + c[i]];
if(i * 2 <= n)
bs[i] |= bs[i * 2];
ans = max(ans, (int)bs[i].count());
}
cout << ans << "\n";
return 0;
}
最長迴文前字尾
#include<bits/stdc++.h>
using namespace std;
int solve(string &s)
{
int len = s.size();
int ans = 0, tmp = 0;
int j = len - 1;
for(int i = 0; i < j; i++)
{
if(s[i] == s[j])
{
j--;
tmp++;
ans = max(ans, tmp);
}
else
{
j = len - 1;
tmp = 0;
if(s[i] == s[j]) // 當前雖然失配,但可能和第一個位置是匹配的
{
j--;
tmp++;
ans = max(ans, tmp);
}
}
}
tmp = 0, j = len - 1;
reverse(s.begin(), s.end());
for(int i = 0; i < j; i++)
{
if(s[i] == s[j])
{
j--;
tmp++;
ans = max(ans, tmp);
}
else
{
j = len - 1;
tmp = 0;
if(s[i] == s[j])
{
j--;
tmp++;
ans = max(ans, tmp);
}
}
}
return ans;
}
int main()
{
string s;
cin >> s;
int l = 0, r = s.size() - 1;
while(l < r && s[l] == s[r])
l++, r--;
if(l >= r)
cout << l << "\n";
else
{
s = s.substr(l, r - l + 1);
cout << l + solve(s) << "\n";
}
return 0;
}