A
找dfs这三个字符即可
cpp
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 55;
int n;
char s[N];
void solve()
{
cin >> n >> s + 1;
int pos1 = -1, pos2 = -1, pos3 = -1;
int f1 = 1, f2 = 1;
for(int i = 1; i <= n; i ++)
{
if(s[i] == 'D')
{
pos1 = i;
break;
}
}
if(pos1 == -1)f1 = 0;
for(int i = n; i >= 1; i --)
{
if(s[i] == 'S')
{
pos3 = i;
break;
}
}
if(pos3 == -1)f1 = 0;
for(int i = pos1 + 1; i < pos3; i ++)
{
if(s[i] == 'F')
{
pos2 = i;
break;
}
}
if(pos2 == -1)f1 = 0;
pos1 = -1, pos2 = -1, pos3 = -1;
for(int i = 1; i <= n; i ++)
{
if(s[i] == 'd')
{
pos1 = i;
break;
}
}
if(pos1 == -1)f2 = 0;
for(int i = n; i >= 1; i --)
{
if(s[i] == 's')
{
pos3 = i;
break;
}
}
if(pos3 == -1)f2 = 0;
for(int i = pos1 + 1; i < pos3; i ++)
{
if(s[i] == 'f')
{
pos2 = i;
break;
}
}
if(pos2 == -1)f2 = 0;
cout << f1 << ' ' << f2 << endl;
}
int main()
{
IOS
int _;
cin >> _;
while(_ --)
{
solve();
}
return 0;
}
B
枚举情况
考虑左右各堵住了几格和特判(1,-1)(1,1)(2,0)这三个点
cpp
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 100010;
void solve()
{
int n;
cin >> n;
map<PII, int> mp;
for(int i = 0; i < n; i ++)
{
int x, y;
cin >> x >> y;
mp[{x, y}] = 1;
}
int l = 0, r = 0;
for(auto t : mp)
{
int x = t.first.first, y = t.first.second;
//cout << "===" << x << ' ' << y << endl;
if(y < 0)
{
l = max(l, 1);
int tmp = 1;
if(x == 1)tmp = 2;
if(mp.count({tmp, y - 1}) || mp.count({tmp, y}) || mp.count({tmp, y + 1}))
{
l = 2;
}
}
else if(y > 0)
{
r = max(r, 1);
int tmp = 1;
if(x == 1)tmp = 2;
if(mp.count({tmp, y - 1}) || mp.count({tmp, y}) || mp.count({tmp, y + 1}))
{
r = 2;
}
}
}
int res = 4 - l - r;
int tmp = 4;
if(mp[{2, 0}])
{
tmp = 2;
if(mp[{1, -1}])tmp --;
if(mp[{1, 1}])tmp --;
if(r == 2)res = min(res, 1);
if(l == 2)res = min(res, 1);
}
res = min(res, tmp);
if(mp[{1, -1}])
{
res = min(res, 2);
if(mp[{1, 1}])res = min(res, 1);
}
if(mp[{1, 1}])
{
res = min(res, 2);
}
res = min(res, 3);
cout << res << endl;
}
int main()
{
IOS
int _;
cin >> _;
while(_ --)
{
solve();
}
return 0;
}
C
可以排序然后前缀和预处理出来在哪个人前面插队增加的时间,对每次询问可以二分来找
cpp
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 100010;
ll a[N], b[N];
void solve()
{
int n, Q, t;
cin >> n >> Q >> t;
for(int i = 1; i <= n; i ++)cin >> a[i];
sort(a + 1, a + 1 + n);
for(int i = 1; i <= n; i ++)a[i] += a[i - 1];
for(int i = 1; i <= n; i ++)//第i个时刻前插队
{
b[i] = (ll)(n - i + 1) * t;
}
b[n + 1] = 0;
while(Q --)
{
ll x;
cin >> x;
int l = 1, r = n + 1;
while(l < r)
{
int mid = l + r >> 1;
if(b[mid] <= x)r = mid;
else l = mid + 1;
}
cout << a[l - 1] + t << endl;
}
}
int main()
{
IOS
int _ = 1;
//cin >> _;
while(_ --)
{
solve();
}
return 0;
}
E
范围只有10,可以3的n次方枚举所有情况
cpp
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 15;
int a[N], b[N];
int q1[N], q2[N];
void solve()
{
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i ++)cin >> a[i];
for(int i = 0; i < m; i ++)
{
cin >> q1[i] >> q2[i];
}
int num = 1;
for(int i = 0; i < m; i ++)num *= 3;
int ans = 2e9;
for(int i = 0; i < num; i ++)
{
for(int j = 1; j <= n; j ++)b[j] = a[j];
int t = i;
for(int j = 0; j < m; j ++)
{
int A = q1[j], B = q2[j];
if(t % 3 == 0)
{
b[A] += 3;
}
else if(t % 3 == 1)
{
b[B] += 3;
}
else
{
b[A] ++;
b[B] ++;
}
t /= 3;
}
int x = b[1];
sort(b + 1, b + 1 + n);
int l = 1, r = n;
while(l < r)
{
int mid = l + r + 1 >> 1;
if(b[mid] <= x)l = mid;
else r = mid - 1;
}
ans = min(ans, n + 1 - l);
}
cout << ans << endl;
}
int main()
{
IOS
int _;
cin >> _;
while(_ --)
{
solve();
}
return 0;
}
F
第二类斯特林数
将n个不同的元素分为k个集合 或者 将n个不同的小球放进k个相同的箱子
S(n, k) = S(n - 1, k) + k * S(n - 1, k)
n=k时为1,S(n, k) = 1
S(n, 0) = 0,特别地S(0, 0) = 1
容斥原理计算公式
搭配快速幂可以mlogn求出来
cpp
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 100010, mod = 1e9 + 7;
int n, m;
int fact[N], infact[N], inv[N];
int C(int a, int b)
{
if(a < b)return 0;
return (ll)fact[a] * infact[b] % mod * infact[a - b] % mod;
}
ll qmi(ll a, ll k)
{
ll res = 1;
while(k)
{
if(k & 1)res = res * a % mod;
a = a * a % mod;
k >>= 1;
}
return res;
}
int main()
{
IOS
fact[0] = fact[1]= infact[0] = infact[1] = inv[1] = 1;
for(int i = 2; i < N; i ++)
{
fact[i] = ((ll)fact[i - 1] * i) % mod;
inv[i] = (ll)(mod - mod / i) * inv[mod % i] % mod;
infact[i] = (ll)infact[i - 1] * inv[i] % mod;
}
cin >> n >> m;
int sign = 1;
ll ans = 0;
for(int k = 0; k <= m; k ++)
{
ll res = C(m, k) * qmi(m - k, n) % mod * sign;
ans = (ans + res) % mod;
sign *= -1;
}
ans = (ans + mod) % mod;
ll tmp = 1;
for(int i = 2; i <= m; i ++)
{
tmp = tmp * i % mod;
}
ans = ans * qmi(tmp, mod - 2) % mod;
cout << ans;
return 0;
}
G
本金+b[i] >= a[i]时就说明可以买,可以先把所有b[i]加到本金里,然后从最大的a[i]往小枚举,不满足的话就-b[i]
cpp
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 100010;
PII a[N];
bool cmp(PII A, PII B)
{
return A.first - A.second < B.first - B.second;
}
void solve()
{
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i ++)
{
int x, y;
cin >> x >> y;
a[i] = {x, y};
}
sort(a + 1, a + 1 + n);
ll t = m;
for(int i = 1; i <= n; i ++)
{
t += a[i].second;
}
for(int i = n; i >= 1; i --)
{
if(t < a[i].first)
{
t -= a[i].second;
}
}
cout << t << endl;
}
int main()
{
IOS
int _;
cin >> _;
while(_ --)
{
solve();
}
return 0;
}
H
标题说是背包但其实解法跟背包也没什么关系
如果背包容量为10101 (二进制)
物品重量为10101 10011
如果选了第一个物品第二个就选不了,如果选了第二个第一个就选不了,无法同时选
可以考虑将背包容量的某一位1强制转为0,然后这一位上为1的物品都不选,只要在这一位之前,物品的重量的位为1时背包这一位也为1就说明可选。这一位之后怎么都无所谓的,不论怎么选都会小于原背包容量的
这样在每次过程中每个物品都变成了可选和不可选两种情况。
然后背包原重量也这么来一遍,取一个最大值即可
这样枚举是包含所有情况的
cpp
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 100010;
int n, m;
int v[N], w[N];
void solve()
{
cin >> n >> m;
for(int i = 1; i <= n; i ++)
{
cin >> v[i] >> w[i];
}
ll ans = 0;
for(int i = 1; i <= n; i ++)
{
if((w[i] | m) == m)
{
ans += v[i];
}
}
while(m)
{
if(m & 1)
{
m >>= 1;
ll res = 0;
for(int i = 1; i <= n; i ++)
{
if(w[i] & 1)
{
w[i] >>= 1;
continue;
}
w[i] >>= 1;
if((w[i] | m) == m)
{
res += v[i];
}
}
ans = max(ans, res);
}
else
{
m >>= 1;
for(int i = 1; i <= n; i ++)w[i] >>= 1;
}
}
cout << ans << endl;
}
int main()
{
IOS
int _;
cin >> _;
while(_ --)
{
solve();
}
return 0;
}
I
正统解法其实是看点的分布概率,第一个人的点分布概率是平均的,第二个人的点分布概率是偏中心的。
我想的是算两个人半径的期望,第二个人的期望一定比第一个人的期望大
最终半径的平均值离谁更近就说明是谁,那肯定有一个临界值,我的想法是找这个临界值
或者也可以真的按这两个人的办法分别模拟1e5或者更多次,看期望是多少
cpp
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
int main()
{
IOS
int n;
cin >> n;
double r = 0;
for(int i = 1; i <= n; i ++)
{
double tmp;
cin >> tmp >> tmp >> tmp;
r += tmp;
}
r /= (double)n;
if(r <= 20.0)cout << "bit-noob";
else cout << "buaa-noob";
return 0;
}
K
一个题的选项是对应题的答案,可以构建出一个基环树(其实是若干个基环树,或者说森林)。
一个环可以有好几条链,所以从链的起点出发其实不好算,但也可以发现后者答案固定后前者的答案是可以逆推出来的,所以可以从一个环上的任意一个点当成起点出发,枚举A-F选项,如果选项合理就计入答案
最终答案数其实就是每个环的方案数相乘
这里学到了一种很好写的方法,用vector存这次遍历到的所有点,然后看最后一个点的下一个点是否在vector中,如果在就说明有环,把这个点之前的点清除剩下的就是一个环。如果最后一个点的下一个点没在vector中就说明没环(环已经被标记了),非常方便的写法
cpp
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 100010, mod = 998244353;
int n;
int a[N];
string s[N];
bool st[N];
int main()
{
IOS
cin >> n;
for(int i = 1; i <= n; i ++)
{
cin >> a[i] >> s[i];
}
ll ans = 1;
for(int i = 1; i <= n; i ++)
{
if(st[i])continue;
int j = i;
vector<int> v;
for(; !st[j]; j = a[j])
{
st[j] = true;
v.push_back(j);
}
vector<int>::iterator it = find(v.begin(), v.end(), j);
if(it == v.end())continue;
v.erase(v.begin(), it);//这样只剩下环里的点了
ll res = 0;
for(char ch = 'A'; ch <= 'E'; ch ++)
{
int t = ch - 'A';
for(auto x : v)
{
t = s[x][t] - 'A';
}
if(ch - 'A' == t)res ++;
}
ans = ans * res % mod;
}
cout << ans;
return 0;
}
L
cpp
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 100010;
ll a[N], b[N];
void solve()
{
ll c, d, h, w;
cin >> c >> d >> h >> w;
cout << 3 * w * c << endl;
}
int main()
{
IOS
int _;
cin >> _;
while(_ --)
{
solve();
}
return 0;
}
M
cpp
#include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
#define endl '\n'
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
const int N = 55;
void solve()
{
int n;
cin >> n;
if(n % 6)
{
cout << n / 6 * 2 << endl;
}
else cout << n / 6 << endl;
}
int main()
{
IOS
int _;
cin >> _;
while(_ --)
{
solve();
}
return 0;
}