CSP-J模拟赛二补题

日期:2023.10.3

学号:S08631

一:

总分数:

T1【称心如意(satisfied)】:100

T2【AC万岁(acok)】:70

T3【解救达达rescue)】:0

T4【整理文本(text)】:10

二、比赛过程

第一道题属于送分题,但是我在做的时候把这道题想的很复杂,后来灵机一动,就突然做了出来。

第二道题也是送分题,但我依然想的的很复杂,本来一个循环就行,我非得用暴力枚举,所以只有70分。

第三道题我想用数组来保存数,可惜想法很好,但无法输出,只有0分

第四题就纯属蒙的了

三、比赛分析

T1【称心如意(satisfied)】:

1、题目大意

输入一个n,下一行有n+1个元素,每个元素为j,j要满足i%(n/j)==0,否则输出"-"

2、比赛中的思考

刚开始时有点懵,想的是先循环n+1次,在循环里再定义一个标记变量,然后再在循环里面循环9次,从循环里判断是否符合条件,符合标记不变,不符合就变,再从外层输出;

3、解题思路

n的范围也并不大,可以直接进行枚举每一个数字,然后再枚举j的范围
(从1到9),判断是否符合条件。事实证明,和我想得差不多。

4、AC代码

#include <iostream>
using namespace std;
int main(){
    int n;
    cin >> n;
 
    string s;
    for(int i = 0; i <= n; i++){
        s += "-";
        for(int j = 1; j <= 9; j++){
            if(n % j == 0 && i % (n/j) == 0){
                s[i] = j + '0';
                break;
            }
        }
    }
    cout << s << endl;
    return 0;
}

T2【AC万岁(acok)】:

1、题目大意

输入一个字符串,判断有多少的字串有“ac”。

2、比赛中的思考

我想的是先用一个循环控制子串开头,然后再一个循环判断后面有多少个ac,如果有计数器就+1,最后输出计数器

3、比赛思路

通过一层循环、两个判断,第一个判断计数 a 有多少。第二个判断 a[ i ]是否为 c ,如果是 c ,就累加计数器,累加答案。并不需要双层循环,也不需要暴力枚举。

4、AC代码

#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <vector>
using namespace std;
#define TIE ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
typedef pair<int, int> pii;
typedef long long ll;
typedef unsigned long long ull;
const int N = 1e5 + 10, M = 1e5 + 10;
const double PI = acos(-1.0);
const double eps = 1e-6;
const ll mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
string s;
int a[N], c[N];
int main() {
    TIE;
    cin >> s;
    int l = s.size();
    if (s[l - 1] == 'c')
    c[l - 1] = 1;
    for (int i = l - 1; i >= 0; i--) {
        if (s[i] == 'c')
            c[i] = 1;
            c[i] += c[i + 1];
    }
    int ans = 0;
    for (int i = 0; i < l; i++) {
        if (s[i] == 'a')
        ans += c[i];
    }
    cout << ans << endl;
    return 0;
}

T3【解救达达rescue)】

1、题目大意

判断 a 到 b 有多少数的二进制的 = 1 , 最后输出

2、比赛中的思考

我想讲十进制转成二进制后存在数组中,再遍历数组

3、比赛思路

可以使用位运算,例如 1<<6 表示1000000,减去1就成了 111111,那么只需要根据题目给的数据范围,通过  ^  来判断是否在  a~b  的二进制的范围内。如果得到的数在给定的范围内,就可以循环判断了,注意:由于数据范围过大,(包括1)所有数据都要定义成为 long long 类型。

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。第二行,一个长度为n的数据),判断整理出来的文本是否满足行首为当前行的第一个单词,相邻的两个单词需至少由一个空格间隔。注意:单词不能调换顺序,并且单词不能舍弃一部分。

2、比赛中的思考

3、比赛思路

数据下,宽度的取值一定是具有单调性的,可以进行二分查找,二分的范围为,每个单
词的最大长度到一个很大的数字(可以装下全部单词),然后贪心验证每个枚举出来的宽度是否满足 行装下所有单词。

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);
   return 0;
   }
bool calc(long long num){
    long long now=1,sum=-1;
    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;
     }
     return false;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值