日期: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;
}