第十六程协杯程序设计竞赛
A - 营救普雷赛斯
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i32 = int32_t;
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = 1e10, INF = 1e18;
const int mod = 998244353;
const int N = 1e6;
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n;
cin >> n;
vi a(n), b(n), vis(n);
for (auto &i: a) cin >> i;
for (auto &i: b) cin >> i;
for (int i = 0, day = 1;; day++) {
if (vis[i]) break;
vis[i] = 1;
i = i + a[i];
if (i >= n) {
cout << day << "\n";
return 0;
}
i = max(0ll, i - b[i]);
}
cout << "-1\n";
return 0;
}
B - 让德克萨斯担任队长
答案是\(\sum_{i=\frac n 2 } ^ n C_n{i}\times(i-1)!\times(n-i)!\)
具体的操作思路是每一个人都选择直接的自己编号的盒子,然后如果不是,就继续选择盒子里面的里面对应的数字。所以不合法的情况,只有当虚拟中出现一个大于$\frac n 2 $的环的。
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i32 = int32_t;
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = 1e10, INF = 1e18;
const int N = 4e5 + 5;
const int mod = 1000000007;
int fact[N];
int infact[N];
int qpow(int a, int b) {
int ans = 1, base = a;
while (b) {
if (b & 1) ans = ans * base % mod;
base = base * base % mod;
b >>= 1;
}
return ans % mod;
}//快速幂模板
void init() {
fact[0] = 1;
infact[0] = 1;
for (int i = 1; i < N; i++) {
fact[i] = (fact[i - 1] * i) % mod;
}
infact[N - 1] = qpow(fact[N - 1], mod - 2);
for (int i = N - 2; i; i--) {
infact[i] = infact[i + 1] * (i + 1) % mod;
}
}//在使用组合数前调用init函数初始化组合数
int C(int a, int b) {
return (fact[a] * (infact[b] * infact[a - b] % mod)) % mod;
}//预处理阶乘,逆元求组合数
void solve() {
int n;
cin >> n;
int res = 0;
for (int i = n / 2 + 1; i <= n; i++)
res = (res + C(n, i) * fact[i - 1] % mod * fact[n - i] % mod) % mod;
cout << res << "\n";
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
init();
int TC;
for (cin >> TC; TC; TC--)
solve();
return 0;
}
C - 简单的签到
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i32 = int32_t;
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = 1e10, INF = 1e18;
const int mod = 998244353;
const int N = 1e6;
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n;
string s;
cin >> n >> s;
int x;
cin >> x;
int res = 0;
for( auto i : s ){
if( i - '0' == x ) res ++;
}
cout << res << "\n";
return 0;
}
D - 安洁莉娜的能量计算
首先\(x!\)的倍数一定是\(k\times x!\),其次\((a_i+1)\times a_1 !=(a_i+1)!\)。所以我们判断一下是否可以把所有的阶乘合并成\(k\times x!\)的形式即可。
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i32 = int32_t;
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = 1e10, INF = 1e18;
const int mod = 998244353;
const int N = 1e6;
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int n, T;
cin >> n >> T;
vi a(T+1);
for( int x ; n ; n -- ){
cin >> x;
a[x] ++;
}
for( int i = 1 ; i < T ; i ++ ){
if( a[i] % ( i + 1 ) == 0 ) a[i+1] += a[i] / (i+1);
else {
cout << "NO\n";
return 0;
}
}
cout << "YES\n";
return 0;
}
E - 保护缪缪
用数电里面类似校验码的做法,对于每一个二进制位用一个分身去验证一下,所以代价就是二进制的长度。
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i32 = int32_t;
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = 1e10, INF = 1e18;
const int mod = 998244353;
const int N = 1e6;
void solve() {
int n, m;
cin >> n >> m;
if (n == 1) {
cout << "0\n";
return;
}
for (int i = 0;; i++) {
if ((1ll << i) < n) continue;
cout << i * m << "\n";
return;
}
return;
}
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int TC;
for (cin >> TC; TC; TC--)
solve();
return 0;
}
F - 我不是可汗
直接dp就好了
#include <bits/stdc++.h>
using namespace std;
#define int long long
using i32 = int32_t;
using vi = vector<int>;
using pii = pair<int, int>;
const int inf = 1e10, INF = 1e18;
const int mod = 998244353;
const int N = 1e6;
i32 main() {
ios::sync_with_stdio(false), cin.tie(nullptr);
int m, n;
cin >> m >> n;
vi v(n + 1), w(n + 1);
string s;
for (int i = 1; i <= n; i++)
cin >> s >> v[i] >> w[i];
vi f(m + 1);
for (int i = 1; i <= n; i++) {
for( int j = m ; j >= v[i] ; j -- )
f[j] = max( f[j] , f[j - v[i]] + w[i] );
}
cout << *max_element(f.begin(), f.end()) << "\n";
return 0;
}