2023杭电第二场补题报告1001 1002 1004 1007 1009
1001 Alice Game (hdu.edu.cn)
思路
题目比较难读,读完题其实就不是很难了,很明显是一个nim游戏的变体,难的地方在于要写出sg函数然后打表找规律,最后ac代码就几行。
代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second
using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n,k;
int a[N];
void solve() {
cin >> k >> n;
if (((n - 2) % (4 * k + 2) == k - 1 && n > k) || n == 0)
cout << "Bob\n";
else
cout << "Alice\n";
}
signed main() {
IOS;
int t = 1;
cin >> t;
for (int i = 1; i <= t; i++) {
solve();
}
}
1002 Binary Number (hdu.edu.cn)
思路
直接贪心,因为翻转一连串01串将其变成全1的次数其实就是连续0的段数。所以我们为了让字典序尽可能大,首先要数出从前往后一共有多少连续0的子段,如果子段数小于等于k,那就尽可能先翻转前面的再反转后面的。如果有剩余,我们发现只要不是全1串或者是全1串但是操作次数不为1且全1串长度不为1,都可以变成全1,剩下的就只能让末位变0。
代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second
using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n, k;
int a[N];
void solve() {
string s;
cin >> n >> k;
cin >> s;
int l = -1;
bool ok = 0;
for (int i = 0; s[i]; i++) {
if (s[i] == '0') {
if (l == -1) l = i;
} else {
if (l != -1) k--, ok = 1;
if (k == 0) {
for (int j = 0; j < i; j++) cout << "1";
for (int j = i; j < n; j++) cout << s[j];
cout << "\n";
return;
}
l = -1;
}
}
if (l > 0) k--, ok = 1;
if ((k && ok) || !k) {
for (int i = 0; i < n; i++) cout << '1';
cout << "\n";
} else if (k % 2) {
if (k == 1 || n == 1) {
for (int i = 0; i < n - 1; i++) cout << '1';
cout << "0\n";
} else {
for (int i = 0; i < n; i++) cout << '1';
cout << "\n";
}
} else {
for (int i = 0; i < n; i++) cout << '1';
cout << "\n";
}
}
signed main() {
IOS;
int t = 1;
cin >> t;
for (int i = 1; i <= t; i++) {
solve();
}
}
1004 Card Game (hdu.edu.cn)
思路
打表手动模拟然后猜结论,严谨证明过于复杂。。。
代码
#include <bits/stdc++.h>
#define int long long
#define ll long long
#define endl '\n'
#define P pair<int,int>
#define FOR(i,n) for(int i = 1;i <= n;i ++)
using namespace std;
const int N = 2e5 + 10;
const int mod = 998244353;
const int INF = 0x3f3f3f3f3f3f3f;
int n,m,x,y,t,k,a[N];
int qpow(int a,int b)
{
int ans=1;
while(b){
if(b&1)
ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
void solve() {
cin >> n;
cout << (qpow(2,n-1) - 1 + mod) % mod << endl;
}
signed main() {
ios_base::sync_with_stdio(0),cin.tie(0);
cin >> t;
while(t--) solve();
return 0;
}
1007 foreverlasting and fried-chicken (hdu.edu.cn)
思路
很像去年杭电多校的火柴人计数,但是需要加入bitset优化,这样复杂度就是 n 3 32 \frac{n^3}{32} 32n3,就跑的飞快,比较坑的是注意组合数的时候在记录上面两个分叉的时候有可能i,j两点之间也有边相连也计入了。
代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve();
void init();
signed main() {
cin.sync_with_stdio(0);
cin.tie(0);
int T = 1;
cin >> T;
init();
while (T--) {
solve();
}
return 0;
}
#define N 1010
#define mod 1000000007
int fac[N];
int inv[N];
int qpow(int a, int p) {
int r = 1;
while (p) {
if (p & 1) {
(r *= a) %= mod;
}
(a *= a) %= mod;
p >>= 1;
}
return r;
}
void init() {
fac[0] = 1;
for (int i = 1; i < N; i++) {
fac[i] = fac[i - 1] * i % mod;
assert(fac[i] > 0);
}
inv[N - 1] = qpow(fac[N - 1], mod - 2);
for (int i = N - 2; i >= 0; i--) {
inv[i] = inv[i + 1] * (i + 1) % mod;
assert(inv[i] > 0);
}
}
int C(int m, int n) {
if (n > m)
return 0;
else
return fac[m] * inv[m - n] % mod * inv[n] % mod;
}
vector<int> g[N];
int k[N][N];
int exi[N][N];
void solve() {
int n;
cin >> n;
bitset<N> bt[n + 1];
for (int i = 1; i <= n; i++) {
g[i].clear();
}
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= n; j++) {
k[i][j] = 0;
exi[i][j] = 0;
}
}
int m;
cin >> m;
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
bt[u].set(v, true);
bt[v].set(u, true);
}
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
k[i][j] = (bt[i] & bt[j]).count();
}
}
int ans = 0;
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
int f = 0;
if (bt[i][j]) {
f = 1;
}
ans += C(k[i][j], 4) *
(C(g[i].size() - 4 - f, 2) + C(g[j].size() - 4 - f, 2) % mod) %
mod;
ans %= mod;
}
}
cout << ans << "\n";
}
1009 String Problem (hdu.edu.cn)
思路
如果要求回文串含不止一种字母其实可能还很复杂,但是由于只含一种字母,所以只需要找连续的相同字符串即可,对于其他的,直接当做长度为1的并不影响结果(+1-1)。
代码
#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define fi first
#define sc second
using namespace std;
const int INF = 0x3f3f3f3f3f3f3f3f;
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
typedef pair<int, int> PII;
int n;
int a[N];
void solve() {
string s;
cin >> s;
int l = 0;
int k = 0;
for (int i = 0; s[i]; i++) {
if (s[l] == s[i])
continue;
else {
k++;
l = i;
}
}
k++;
cout << s.length() - k << "\n";
}
signed main() {
IOS;
int t = 1;
cin >> t;
for (int i = 1; i <= t; i++) {
solve();
}
}