目录
一、题目报告
比赛中第一题AC,第二题0分,第三题10分,第四题20分。赛后一到三题AC。
二、解题报告
T1.交替出场(alter)
题目情况
比赛时AC
题目大意
给定一个只含字符0和1的字符串s,求其中有多少个 01 交替子串,即前一位不同于后一位的字符串,长度为1的字符串也被定义为交替串。
题目解析
枚举左端点,一位一位向右扩展即可得出答案。
正解代码
#include<bits/stdc++.h>
using namespace std;
string s;
char a;
long long cnt;
int main(){
freopen("alter.in","r",stdin);
freopen("alter.out","w",stdout);
cin>>s;
cnt+=s.size();
for(int i=0;i<s.size();i++){
a=s[i];
for(int j=i+1;j<s.size();j++){
if(s[j]!=a){
cnt++;
a=s[j];
}
else{
break;
}
}
}
cout<<cnt;
fclose(stdin);
fclose(stdout);
return 0;
}
T2.翻翻转转(filp)
题目情况
比赛时0分,后AC
题目大意
给定字符串
s0=1
𝑠1=10
𝑠2=1001
𝑠3=10010110
⋯⋯
si是si-1逐位取反后拼接在si-1后的串,求s114514的第x个字符(多组测试样例)
题目解析
一开始想到打表,但是没做出来。且本题数据范围较大,打表会MLE。进一步分析发现序列的构成有规律,前一半和后一半是互反的
可以使用分治,如果答案处在前半段,继续递归,反之将递归上来的答案取反后上传即可。
正解代码
#include <bits/stdc++.h>
using namespace std;
int x;
void solve(int l, int r, bool p) {
if (l == x && r == x) {
cout << (p == true ? 1 : 0) << "\n";
return;
}
int mid = (l + r) / 2;
if (x <= mid)
solve(l, mid, p);
else
solve(mid + 1, r, !p);
}
int main() {
int t;
cin >> t;
while (t--) {
scanf("%d", &x);
solve(1, 1 << 30, true);
}
}
T3.方格取数(square)
题目情况
比赛时10分,赛后AC
题目大意
给出一个n行m列的方格,每个格子都有一个数字,从(1,1)出发到(n,m),只能向右或下走且向一个方向最多一次性走k-1步,走过便能收集这个方格里的数字,求到(n,m)时收集到的数字的和的最大值,若无解,则输出No Answer!。
题目解析
比赛时想到用dfs,且欠缺考虑,只得了10分。正解应用dp,设置dp数组为四维数组:dp[x][y][k][s]。分别为位置(x,y),向一个方向走了k步,且该方向为s。
状态转移方程:
1.方向不同:dp[xx][yy][1][nd]=max(dp[xx][yy][1][nd],dp[x][y][l][d]+a[xx][yy]);
2.方向相同:dp[xx][yy][l+1][nd]=max(dp[xx][yy][l+1][nd],dp[x][y][l][d]+a[xx][yy]);
正解代码
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N = 210;
ll dx[2] = {1, 0}, dy[2] = {0, 1};ll n, m, k, a[N][N], dp[N][N][N][2], ans = -1e18;
int main() {
cin >> n >> m >> k;
for (ll i = 1; i <= n; i++)
for (ll j = 1; j <= m; j++)
cin >> a[i][j];
memset(dp, -0x3f, sizeof(dp));dp[1][1][0][0] = dp[1][1][0][1] = a[1][1];
for (ll x = 1; x <= n; x++)
for (ll y = 1; y <= m; y++)
for (ll l = 0; l < k; l++)
for (ll d = 0; d <= 1; d++) {
for (ll nd = 0; nd <= 1; nd++) {
ll nx = x + dx[nd], ny = y + dy[nd];
if (nx < 1 || nx > n || ny < 1 || ny > m)continue;
if (d != nd)
dp[nx][ny][1][nd] = max(dp[nx][ny][1][nd], dp[x][y][l][d] + a[nx][ny]);
else if (l < k - 1)
dp[nx][ny][l + 1][nd] =max(dp[nx][ny][l + 1][nd], dp[x][y][l][d] +a[nx][ny]);
}
}
for (ll l = 0; l < k; l++)
for (ll d = 0; d <= 1; d++)
ans = max(ans, dp[n][m][l][d]);
if (ans == -1e18)
cout << "No Answer!";
else
cout << ans;
return 0;
}
T4.圆圆中的方方(round)
题目情况
比赛时20分
题目大意
给定了一个圆和一个矩形,求两个图形相交的面积
题目解析
骗分骗了20。
考虑将整块面积分为四部分,圆心的左上,圆心的左下,圆心的右上,圆心的右下。那么问题将转化为了,一个圆心在角落的 圆与矩形的面积交。
经过一系列对称后可以保证与下图同构。
容易把问题划分成四种情况。
图1,4可以直接计算,图2,3可以分割为三角形和扇形计算
感谢dalao的图
正解代码
#include <bits/stdc++.h>
using namespace std;
const double pi = acos(-1), eps = 1e-6;
double n, m, x, y, r;
double calc(double n, double m, double r) {
if (n > m)
swap(n, m);
if (n < eps || m < eps)
return 0;
if (r <= n)
return 0.25 * pi * r * r;
else if (r <= m) {
double tt = sqrt(r * r - n * n);double res = n * tt / 2.0;double ang = pi / 2 - acos(n / r);
res += ang / 2 * r * r;
return res;
}
else if (r <= sqrt(n * n + m * m)) {
double t1 = sqrt(r * r - n * n), t2 = sqrt(r * r - m * m);double res = n * t1 / 2.0 + m * t2 / 2.0;double ang = pi / 2 - acos(n / r) - acos(m / r);
res += ang / 2 * r * r;
return res;
}
else
return n * m;
}
int main() {
cin >> n >> m >> x >> y >> r;
cout << fixed << setprecision(10)<< calc(x, y, r) + calc(x, m - y, r) + calc(n - x, y, r) +calc(n - x, m - y, r)<< endl;
return 0;
}
总结
本场考试自我感觉还可以,就是第二题有点考虑欠缺,没有注意数据范围,考虑到寻找规律,应该继续去加强自己的思维能力。
2024/10/1