CSP-X模拟赛刘彦孜补题

日期:2023.10.3
学号:S06465
一:
总分数:
T1【称心如意(satisfied)】:100
T2【AC万岁(acok)】:100
T3【解救达达(rescue)】:40
T4【整理文本(text)】:0
二、比赛过程
第一道题送分题,读懂题目就能拿满分
第二道题也很简单,就是要注意一下a在c后面不算ac
第三道题我用的是暴力枚举,得了40
第四道题我用的暴力枚举,我的思路对了,但是没有考虑空格,得0分
三、比赛分析
T1【称心如意(satisfied)】:
1.题目大意
小可有一个数字,让你根据要求找到一个与其匹配的序列
2、比赛中的思考
我是读懂题目以后,直接根据要求模拟的
3、解题思路
根据题目要求直接模拟就可以了
4.AC代码

#include<bits/stdc++.h>
using namespace std;
int main(){
	int n;
	cin>>n;
	for(int i=0;i<=n;i++){
		int f=0;
		for(int j=1;j<=9;j++){
			if(n%j==0&&i%(n/j)==0&&f==0){
				f=1;
				cout<<j;
			}
		}
		if(f==0){
			cout<<"-";
		}
	}
	return 0;
} 

T2【AC万岁(acok)】:
1.题目大意
给你一个字符串,让你求ac作为字符串子序列出现的次数
2.比赛中的思考
我一开始想的是统计出a和c出现的次数,然后输出把它们相乘的结果,后来想到a在c的后面不算ac,然后又想的如果遇到a就让cnt++,如果碰到c就让sum加上cnt
3.解题思路
for循环遍历字符串s,如果遇到a,就让计数器++,如果遇到c就让sum+=计数器,最后输出sum
4.AC代码

#include<bits/stdc++.h>
using namespace std;
int main(){
	string s;
	cin>>s;
	int a=0,cnt=0;
	for(int i=0;i<s.size();i++){
		if(s[i]=='a'){
			a++;
		}
		if(s[i]=='c'){
			cnt+=a;
		}
	}
	cout<<cnt;
	return 0;
}

T3【解救达达(rescue)】:
1.题目大意
给你一个区间[a,b]让你求这个区间内,把这几个数转成二进制,这个二进制里有一个只有一个0的数
2.比赛中的思考
我是这样想的,先for循环遍历a到b,然后再把i转成二进制数,如果这个二进制位上有一个0,就让计数器++,如果计数器等于1,就让sum++,最后输出sum
3.解题思路
先记录一下a和b转成二进制是几位数,然后在用循环枚举,用((long long)1<<cnt1)-1,求出这个cnt1位的二进制最大的数,然后for循环枚举,每一次都用x^((long long)1<<j),把它的第j位变成0,如果这个二进制大于等于a并且小于等于b,让cnt++,最后输出cnt
4.AC代码

#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
int main(){
	long long a, b;
 	cin >> a >> b;
    long long cnt = 0;
    for (int i = 1; i <= 63; i ++) {
        for (int j = 0; j < i - 1; j ++) {
            long long sum = (1ll << i) - 1 - (1ll << j);
            if (sum >= a && sum <= b)
            	cnt ++;
        }
    }
    cout << cnt;
    return 0;
}

T4【整理文本(text)】:
1.题目大意
给你n个单词,让你整理这些单词,并且要把行数控制在m行以内,两个单词之间至少要有一个空格,单词不能调换顺序,并且单词不能舍弃一部分
2.比赛中的思考
我想的是用for循环枚举它的宽度,如果sum加a[i]小于等于i,就让sum加上a[i],如果大于i就让sum等于0,cnt++,如果cnt小于等于m,就用它和minn比较,如果minn比它大,就让minn等于cnt
3.解题思路
可以用二分答案来解决,用一个函数来判断这个宽度可不可以满足要求,如果可以,就让r=mid,继续寻找看看有没有更小的答案,如果不可以就让l=mid+1,直接越过这个去继续寻找
4.AC代码

#include<bits/stdc++.h>
#define N 220000
using namespace std;
long long a[N]={},m=0,mx=0,n=0;
bool calc(long long num);
int main(){
 	scanf("%lld%lld",&n,&m);
 	for(long long i=1;i<=n;i++){
 	scanf("%lld",&a[i]);
 	mx=max(mx,a[i]);
 	}
 	//输入,并找到单词长度最大值
 	long long l=mx-1,r=1e15+1;
 	//确定双端便边界,开始二分
 	while(l+1<r){
	 	long long mid=(l+r)/2;
	 	if(calc(mid)==false){
	 		l=mid;
	 	}
		else{
	 		r=mid;
	 	}
 	}
 	printf("%lld\n",r);
//输出答案r
 	return 0;
	}
bool calc(long long num){
 	long long now=1,sum=-1;
 	//now为当前用到第几行,sum表示用到第now行的第几列 //初始值是为了把第一个单词前面的空格磨平
 	for(long long i=1;i<=n;i++){
	 	if(sum+1+a[i]<=num){
	 		sum=sum+1+a[i];
	 	//当前行能在放就放
	 	}else{
	 		sum=a[i];
	 		now++;
	 	//放不了就另起一行
	 	}
 	}
  	if(sum==-1){
 			now--;
 	}
 	//把初始值的误差过滤掉
 	if(now<=m){
 		return true;
 	}
 	//符合条件返回true
 	return false;
 	//否则返回false
    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值