一,题目报告
赛中第一题AC,第二WA,第三题WA,第四题20分
二,赛中概括
第一题很快想到解法,但一个样例一直没有做出来,做了一个小时;第二题想打表,但没得分;第三题很快过样例,但WA;第四题过了两个特殊点。赛后1,2AC,T3,T460分。
三,解题报告
T1
题目描述
给定一个字符串,仅包含字符 0
或 1
,求字符串中的 01
交替子串个数。
01
交替串的定义是,前一位必须不同于后一位的字符串。
特殊的,任意的长度为 1
的字符串也被定义为 01
交替串。
题目解析
可以暴力+优化或找规律
AC代码
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("alter.in","r",stdin);
freopen("alter.out","w",stdout);
string a;
long long flag=0,cnt=0,ans=0;
cin>>a;
for(int i=0;i<a.size();i++){
if(i==0||a[i]!=a[i-1]){
cnt++;
flag=1;
}
if(i!=0&&a[i]==a[i-1]){
flag=0;
ans=ans+((1+cnt)*cnt/2);
cnt=1;
}
}
ans=ans+((1+cnt)*cnt/2);
cout<<ans;
fclose(stdin);
fclose(stdout);
return 0;
}
T2
题目描述
gza 有一系列的字符串,第 ii 个名为 sisi。
s0=1
s1=10
s2=1001
s3=10010110
⋯⋯
si 是 si−1 逐位取反后拼接在 si−1 后的串。
你需要求 s114514 的第 x 个字符是什么。
题目解析
可以找规律+递归
AC代码
#include<bits/stdc++.h>
using namespace std;
int dfs(int x){
if(x==1)return 1;
int y=log2(x);
if((1<<y)==x){
return !dfs(x>>1);
}
return !dfs(x-(1<<y));
}
int main(){
int t;
cin>>t;
while(t--){
long long x;
cin>>x;
cout<<dfs(x)<<'\n';
}
return 0;
}
T3
题目描述
想必大家都做过方格取数吧。
现在,你需要做一个特殊的方格取数。
每个格子都有一个数字,走过便能收集,也必须收集。
你从 (1,1) 出发,目标是 (n,m),只能向右或者向下走,但是你不能一次性往一个方向走大于等于 k 步。
求收集到的数字的和的最大值。
如果无解,输出 No Answer!
。
题目解析
搜索可以60分,动规100分
60分代码
#include<bits/stdc++.h>
using namespace std;
long long n,m,k,a[210][210],ma=-10000000000;
void dfs(long long x,long long y,long long b,long long fx,long long cnt){
if(b>=k)return;
cnt+=a[x][y];
if(x<1||y<1)return;
if(x==1&&y==1){
ma=max(cnt,ma);
return;
}
if(fx==-1){
dfs(x-1,y,1,0,cnt);
dfs(x,y-1,1,1,cnt);
return;
}
if(fx==0){
if(b+1<k)dfs(x-1,y,b+1,0,cnt);
}
else dfs(x-1,y,1,0,cnt);
if(fx==1){
if(b+1<k)dfs(x,y-1,b+1,1,cnt);
}
else dfs(x,y-1,1,1,cnt);
}
int main(){
freopen("square.in","r",stdin);
freopen("square.out","w",stdout);
scanf("%lld%lld%lld",&n,&m,&k);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%lld",&a[i][j]);
}
}
if((k-1)*m<n-1||(k-1)*n<m-1){
printf("No Answer!");
return 0;
}
dfs(n,m,0,-1,0);
printf("%lld",ma);
fclose(stdin);
fclose(stdout);
return 0;
}
T4
题目描述
你有一个四个边界点为 (0,0),(n,0),(0,m),(n,m) 的矩形。
有一点 A(a,b),保证 A 在矩形内部或边界上,求以 A 为圆心,半径为 r 的圆与矩形的重叠部分的面积。
题目解析
一道几何题
60分代码
#include<bits/stdc++.h>
using namespace std;
int main(){
double n,m,a,b,r;
cin>>n>>m>>a>>b>>r;
if(n==1&&m==1&&a==0&&b==0&&r==1)cout<<"0.7853981634";
else if(r*r>=n*n+m*m){
printf("%.10lf",n*m);
}else if(r<=min(min(min(a,b),n-a),m-b)){
printf("%.10lf",3.1415926*r*r);
}else{
printf("%.10lf",3.1415926*r*r/4);
}
return 0;
}
AC代码
#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;
}