模拟赛一补题报告

目录

文章目录

一、题目报告

二、解题报告

T1.交替出场(alter)

题目情况

题目大意

题目解析

正解代码

T2.翻翻转转(filp)

题目情况

题目大意

题目解析

正解代码

T3.方格取数(square)

题目情况

题目大意

题目解析

正解代码

T4.圆圆中的方方(round)

题目情况

题目大意

题目解析

正解代码

总结


一、题目报告

  比赛中第一题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

题目大意

  给定字符串

                s​0​​=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

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值