这几天状态一直不太好,训练量比自己预期的要差一大截,焦虑,希望明天可以恢复过来
题目链接
关于第二类斯特林数看这里
#include
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 1000010;
const int maxn = 1e6 + 1;
const int mod = 1e9 + 7;
int Jc[maxn];
void calJc()
{
Jc[0] = Jc[1] = 1;
for(int i = 2; i < maxn; i++) Jc[i] = Jc[i - 1] * i % mod;
}
int pow(int a, int n, int p)
{
int ans = 1;
while (n)
{
if (n & 1) ans = ans * a % p;
a = a * a % p;
n >>= 1;
}
return ans;
}
int niYuan(int a, int b)
{
return pow(a, b - 2, b);
}
int C(int a, int b)
{
if(a < b) return 0;
return Jc[a] * niYuan(Jc[b], mod) % mod * niYuan(Jc[a - b], mod) % mod;
}
int S(int n, int k)
{
int res = 0;
for (int i = 0; i <= k; i ++ )
{
if (i & 1) res = (res - (C(k, i) * pow(k - i, n, mod)) % mod) % mod;
else res = (res + (C(k, i) * pow(k - i, n, mod)) % mod) % mod;
}
while (res < 0) res += mod;
res = res * niYuan(Jc[k], mod) % mod;
return res;
}
void solve()
{
calJc();
int n, m;
cin >> n >> m;
cout << S(n, m) << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
题目链接
参考jiangly代码,二分,check中遍历所有任务,假设一个人在a[i]时看另一个人有多少种位置可以选,存在set里,set如果在某一个时刻为空就说明此mid是不行的
#include
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 1000010;
const int maxn = 1e6 + 1;
const int mod = 1e9 + 7;
void solve()
{
int n, x, y;
cin >> n >> x >> y;
vector<int> a(n);
for (int i = 0; i < n; i ++ ) cin >> a[i];
auto check = [&](int mid)
{
int lst = y;
set<int> st;
if (abs(x - y) > mid) return false;
st.insert(x);
for (int i = 0; i < n; i ++ )
{
if (abs(lst - a[i]) <= mid) st.insert(lst);
while (!st.empty() && abs((*st.begin()) - a[i]) > mid) st.erase(*st.begin());
while (!st.empty() && abs((*st.rbegin()) - a[i]) > mid) st.erase(*st.rbegin());
lst = a[i];
if (st.empty()) return false;
}
return true;
};
int l = 0, r = 1e9;
while (l < r)
{
int mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
cout << r << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
题目链接
基环内向树(准确的说应该是森林)
编号 i 向 a[i] 连边,表示对其限制,我们可以发现环之外的链对答案没什么影响,因为确定了环上一点,可以倒推出链上的所有答案(原因就是约束关系),所以我们在环上任取一点,枚举这个点的五种答案,然后遍历一下环看这个答案是否合法
因为不保证联通,所以需要遍历每一个点
这题还学到了一个技巧,截取vector的一部分可以直接a = {迭代器头,迭代器尾}
(截取出的部分不包括尾部迭代器)
#include
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 1000010;
const int maxn = 1e6 + 1;
const int mod = 998244353;
void solve()
{
int n;
cin >> n;
vector<int> a(n + 1);
vector<string> s(n + 1);
for (int i = 1; i <= n; i ++ ) cin >> a[i] >> s[i];
vector<bool> st(n + 1);
int ans = 1;
for (int i = 1; i <= n; i ++ )
{
if (st[i]) continue;
int j = i;
vector<int> huan;
for (; !st[j]; j = a[j])
{
huan.push_back(j);
st[j] = true;
}
auto iter = find(huan.begin(), huan.end(), j);
if (iter == huan.end()) continue;
huan = {iter, huan.end()};
int tmp = 0;
for (int k = 0; k < 5; k ++ )
{
int h = k;
for (auto t : huan) h = (int)(s[t][h] - 'A');
tmp += h == k;
}
ans = ans * tmp % mod;
}
cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}
题目链接
BFS,用四维数组,dist[i][j][k][z]
表示第一个人在i,j
第二个人在k,z
时的最短路径长度(其他四维数组定义类似)
#include
using namespace std;
#define int long long
using i64 = long long;
typedef pair<int, int> PII;
typedef pair<double, double> PDD;
typedef pair<int, PII> PIII;
const int N = 1000010;
const int maxn = 1e5 + 1;
const int mod = 1e9 + 7;
int dx[4] = {-1, 0, 1, 0}, dy[4] = {0, 1, 0, -1};
void solve()
{
int n;
cin >> n;
vector<vector<char>> g(n + 1, vector<char>(n + 1));
PII start = {0, 0}, end = {0, 0};
for (int i = 1; i <= n; i ++ )
for (int j = 1; j <= n; j ++ )
{
cin >> g[i][j];
if (g[i][j] == 'P')
{
if (start.first == 0) start = make_pair(i, j);
else end = make_pair(i, j);
}
}
vector<vector<vector<vector<int>>>> dist(n + 1, vector<vector<vector<int>>>(n + 1, vector<vector<int>>(n + 1, vector<int>(n + 1, 0x3f3f3f3f3f3f3f3f))));
vector<vector<vector<vector<bool>>>> st(n + 1, vector<vector<vector<bool>>>(n + 1, vector<vector<bool>>(n + 1, vector<bool>(n + 1))));
queue<pair<PII, PII>> q;
q.push({start, end});
dist[start.first][start.second][end.first][end.second] = 0;
st[start.first][start.second][end.first][end.second] = true;
while (!q.empty())
{
auto xs = q.front().first.first, ys = q.front().first.second;
auto xe = q.front().second.first, ye = q.front().second.second;
q.pop();
for (int i = 0; i < 4; i ++ )
{
int xsn = xs + dx[i], xen = xe + dx[i];
int ysn = ys + dy[i], yen = ye + dy[i];
xsn = max(xsn, (i64)1); xsn = min(xsn, n);
xen = max(xen, (i64)1); xen = min(xen, n);
ysn = max(ysn, (i64)1); ysn = min(ysn, n);
yen = max(yen, (i64)1); yen = min(yen, n);
if (g[xsn][ysn] == '#') xsn = xs, ysn = ys;
if (g[xen][yen] == '#') xen = xe, yen = ye;
if (st[xsn][ysn][xen][yen]) continue;
st[xsn][ysn][xen][yen] = true;
dist[xsn][ysn][xen][yen] = dist[xs][ys][xe][ye] + 1;
q.push({{xsn, ysn}, {xen, yen}});
}
}
int ans = 0x3f3f3f3f3f3f3f3f;
for (int i = 1; i <= n; i ++ )
{
for (int j = 1; j <= n; j ++ )
{
ans = min(ans, dist[i][j][i][j]);
}
}
if (ans == 0x3f3f3f3f3f3f3f3f) cout << -1 << '\n';
else cout << ans << '\n';
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
int t = 1;
// cin >> t;
while (t -- )
{
solve();
}
}