CSP-J模拟赛一补题报告

6 篇文章 0 订阅
5 篇文章 0 订阅

IAKIOI!!!

前言

考的最好的一回:240pts
首先开T1,45min干掉了
然后T2,45min挂了
然后T3,40min又挂了
然后发呆了一会把T4 骗分打了 ,此时已过去一坤时
40minT2切了,最后20min打了T3骗分又发呆了一会
T1:100pts
T2:100pts
T3:30pts
T4:10pts

《正文》

0101101010100101001010101101010001101010101000110010101011001010010101001100101010101101100101010101010101010101011010101010101001101010010101010101010010101001010011010010101010010110010101000101010100101010110100101011001101001101101010010101010101001010101001010101100101010101010101100101010100101010100000010101001010100101101010010011000101001010101010101010101010101010101010101001010101010101
0101101010100101001010101101010001101010101000110010101011001010010101001100101010101101100101010101010101010101011010101010101001101010010101010101010010101001010011010010101010010110010101000101010100101010110100101011001101001101101010010101010101001010101001010101100101010101010101100101010100101010100000010101001010100101101010010011000101001010101010101010101010101010101010101001010101010101
1010101010010110010101010101010101101100101010101010101010101010101010101010101010110101010101010100101010010101101010101010011010101010101010100111000110010101
0101101010100101001010101101010001101010101000110010101011001010010101001100101010101101100101010101010101010101011010101010101001101010010101010101010010101001010011010010101010010110010101000101010100101010110100101011001101001101101010010101010101001010101001010101100101010101010101100101010100101010100000010101001010100101101010010011000101001010101010101010101010101010101010101001010101010101
0101101010100101001010101101010001101010101000110010101011001010010101001100101010101101100101010101010101010101011010101010101001101010010101010101010010101001010011010010101010010110010101000101010100101010110100101011001101001101101010010101010101001010101001010101100101010101010101100101010100101010100000010101001010100101101010010011000101001010101010101010101010101010101010101001010101010101
1010101010010110010101010101010101101100101010101010101010101010101010101010101010110101010101010100101010010101101010101010011010101010101010100111000110010101
01010011001010101011010100110001010101011001001010101010111001010101010101010100

T1 交替出场(alter)

简单,秒了

题面

时间限制:1秒 内存限制:256M

题目描述

给定一个字符串,仅包含字符 0 或 1,求字符串中的 01 交替子串个数。

01 交替串的定义是,前一位必须不同于后一位的字符串。

特殊的,任意的长度为 1 的字符串也被定义为 01 交替串。

输入描述

一行,一个字符串 s s s,保证仅包含字符 0 或 1。

输出描述

一行一个整数,表示 s s s 中的 01 交替子串个数。

输入样例

0101

输出样例

10

样例解释

显然的,任意一个子串都是 01 交替子串。

数据范围

定义 n n n 为字符串 s s s 的长度。
对于 20% 数据:

1 ≤ n ≤ 3 1≤n≤3 1n3

对于另外 60% 数据:

1 ≤ n ≤ 100 1≤n≤100 1n100
1 ≤ n ≤ 100 1≤n≤100 1n100

对于全部数据:

1 ≤ n ≤ 1000 1≤n≤1000 1n1000

解析

c n t cnt cnt为找到的01交替子串长度, s i z siz siz为字符串长度
枚举子串的开头 i i i,结尾 j j j
j j j一定要从 i i i按顺序枚举到 s i z e size size
如果子串 [ i , j − 1 ] [i,j-1] [i,j1]不是01交替子串,子串 [ i , j ] [i,j] [i,j]必定也不是,此时直接break。
否则发现了一个新的01交替子串, c n t + + cnt++ cnt++
秒了
s = s= s=" " + s +s +s是为了从一开始扫。

AC Code

#include<bits/stdc++.h>
using namespace std;
string s;
/* 
bool check(long long l,long long r)
{
	for(int i=l+1;i<=r;i++)
	{
		if(s[i]==s[i-1])
		{
			return 0;
		}
	}
	return 1;
}
*/
int main()
{
	freopen("alter.in","r",stdin);
	freopen("alter.out","w",stdout);
	cin>>s;
	long long ans=0,siz=s.size();
	s=" "+s;
	/*
	for(int len=1;len<=siz;len++)
	{
		for(int l=1;l<=siz-len+1;l++)
		{
			long long r=l+len;
			if(check(l,r));
			{
				ans++;
			}
		}
	}
	*/
	//暴力代码保留备用 
	int cnt=0; 
	for(int i=1;i<=siz;i++)
	{
		cnt++;
		for(int j=i+1;j<=siz;j++)
		{
			if(s[j-1]==s[j])
			{
				break;
			}
			cnt++;	
		}
	}
	printf("%d",cnt);
	return 0;
}

T2 翻翻转转(filp)

有难度

题面

时间限制:1秒 内存限制:256M

题目描述

gza 有一系列的字符串,第 i i i个名为 s ​ i s_​i si

s 0 = 1 s_0=1 s0=1
s 1 = 10 s_1=10 s1=10
s 2 = 1001 s_2=1001 s2=1001
s 3 = 10010110 s_3=10010110 s3=10010110

⋯⋯
s ​ i s_​i si s ​ i − 1 s_{​i−1} si1
​​ 逐位取反后拼接在 s ​ i − 1 s_{​i−1} si1
​​ 后的串。

你需要求 s 114514 s_{114514} s114514的第 x x x 个字符是什么。

多测。

输入描述

第一行一个整数 T T T,表示数据组数。

接下来
T T T 行,一行一个整数,表示 x x x,含义见题目描述。

输出描述

一共 T T T 行,一行一个字符,表示答案。

输入样例

1
3

输出样例

0

数据范围

对于 10%的数据:

x ≤ 100 x≤100 x100

对于另外 50% 的数据:

x ≤ 1 0 7 x≤10^7 x107​​ 。

对于全部数据:

x ≤ 1 0 9 x≤10^9 x109

思路

类似倍增
x x x依次尝试减去 2 32 2^{32} 232 2 0 2^0 20
每次操作后, x x x将被取反
如果操作偶数次,则 x x x不变,反之 x x x取反
x x x最后的位置一定为1,值也为1
最后判断是否取反
不要忘记是多组测试数据

AC Code

#include<bits/stdc++.h>
using namespace std;
long long cf[40];
void getpow()
{
	cf[0]=1;
	for(int i=1;i<=32;i++)
	{
		cf[i]=cf[i-1]*2;
	}
}
int main()
{
	freopen("filp.in","r",stdin);
	freopen("filp.out","w",stdout);
	int t;
	getpow();
	scanf("%d",&t);
	while(t--)
	{
		long long x;
		scanf("%lld",&x);
		string s;
		int cnt=0;
		for(int i=32;i>=0;i--)
		{
			if(x>cf[i])
			{
				x-=cf[i];
				cnt++;
			}
		}
		if(cnt%2==0)
		{
			printf("1\n");
		}
		else
		{
			printf("0\n");
		}
	}
	return 0;
}
/*
 ********  ********
*          *       *
*          *       *
*********  ********
        *  *       *
		*  *       *
********   ********

*/
//I AK IOI!!!
/*

*/

方格取数(square)

赛时DP写炸,最后一刻总司令了30pts

题面

时间限制:1秒 内存限制:256M

题目描述

想必大家都做过方格取数吧。

现在,你需要做一个特殊的方格取数。

每个格子都有一个数字,走过便能收集,也必须收集。

你从 ( 1 , 1 ) (1,1) (1,1) 出发,目标是 ( n , m ) (n,m) (n,m),只能向右或者向下走,但是你不能一次性往一个方向走大于等于 k k k 步。

求收集到的数字的和的最大值。

如果无解,输出No Answer!

输入描述

第 1 行三个正整数 n , m , k n,m,k n,m,k

接下来 n n n 行每行 m m m 个整数,依次代表每个方格中的整数。

输出描述

一个整数,表示收集到的数字的和的最大值。

输入样例1

3 3 2
1 1 1
1 1 2
1 1 1

输出样例1

6

输入样例2

3 3 2
1 1 2
1 1 1
2 1 1

输出样例2

5

数据范围

被我吃了

思路

记忆化搜索
i , j i,j i,j为坐标, s t e p step step为向同一个方向走的步数, d d d为方向

AC Code

#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
int n,m,k,a[205][205];
int dx[]={0,1},dy[]={1,0};
pair<int,bool>f[205][205][205][2];
int dfs(int x,int y,int step,int d)
{
	if(x>n||y>m||step>k)
	{
		return -0x3f3f3f3f;
	}
	if(x==n&&y==m)
	{
		return a[x][y];
	}
	if(f[x][y][step][d].second)
	{
		return f[x][y][step][d].first;
	}
	f[x][y][step][d].second=1;
	int ans=-0x3f3f3f3f;
	if(step<k)
	{
		ans=max(ans,dfs(x+dx[d],y+dy[d],step+1,d));
	}
	ans=max(ans,dfs(x+dx[d^1],y+dy[d^1],2,d^1));
	if(ans<-1e9)
	{
		return f[x][y][step][d].first=-0x3f3f3f3f;
	}
	return f[x][y][step][d].first=ans+a[x][y];
}
int main()
{
	freopen("square.in","r",stdin);
	freopen("square.out","w",stdout);
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			scanf("%d",&a[i][j]);
		}
	}
	int tmp=max(dfs(1,2,2,0),dfs(2,1,2,1));
	if(tmp>-1e9)
	{
		printf("%d",tmp+a[1][1]);
		return 0;
	}
	printf("No Answer!");
	return 0;
}
/*

*/ 

T4 圆圆中的方方(round)

完全不会啊qwq

题面

时间限制:1秒 内存限制:256M

题目描述

你有一个四个边界点为 ( 0 , 0 ) , ( n , 0 ) , ( 0 , m ) , ( n , m ) (0,0),(n,0),(0,m),(n,m) (0,0)(n,0)(0,m)(n,m) 的矩形。

有一点 A ( a , b ) A(a,b) A(a,b),保证 A A A在矩形内部或边界上,求以 A A A 为圆心,半径为
r r r 的圆与矩形的重叠部分的面积。

输入描述

一行五个浮点数, n , m , a , b , r n,m,a,b,r n,m,a,b,r,含义见题目描述。

输出描述

一行一个浮点数,表示答案。

输入样例

1 1 0 0 1

输出样例

0.7853981634

数据范围被我吃了

AC Code

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const double pi=acos(-1),eps=1e-8; 
double n,m,a,b,r;
double cal(double n,double m,double r)
{
	if(n<m)
	{
		swap(n,m);
	}
	if(n<=eps||m<=eps)
	{
		return 0;
	}
	if(r<=m)
	{
		return 0.25*pi*r*r;
	}
	if(r>=sqrt(n*n+m*m))
	{
		return n*m;
	}
	if(r<=n)
	{
		return sqrt(r*r-m*m)*m*0.5+0.5*r*r*(0.5*pi-acos(m/r));
	}
	return sqrt(r*r-m*m)*m*0.5+sqrt(r*r-n*n)*n*0.5+0.5*r*r*(0.5*pi-acos(m/r)-acos(n/r));
}
int main()
{
	freopen("round.in","r",stdin);
	freopen("round.out","w",stdout);
	cin>>n>>m>>a>>b>>r;
	printf("%lf",cal(a,b,r)+cal(n-a,b,r)+cal(a,m-b,r)+cal(n-a,m-b,r));
	return 0;
}
/*
 ********  ********
*          *       *
*          *       *
*********  ********
        *  *       *
		*  *       *
********   ********

*/
/*
 ********  *       *   *******   ********    *********
*          *       *      *      *               *
*          *       *      *      *               *
*********  *********      *      ********        *
        *  *       *      *      *               *
		*  *       *      *      *               *
********   *       *   *******   *               *

*/

思路

考虑将整块面积分为四部分,圆心的左上,圆心的左下,圆心的右上,圆心的右下。
那么问题将转化为了,一个圆心在角落的 圆与矩形的面积交。
除去重叠部分为扇形和全部覆盖的,其他情况把图形分割为三角形和扇形计算。
利用亿点点三角函数计算

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值