你是如风的少年~
空 清新民谣版 - 汪小敏 - 单曲 - 网易云音乐
自在的少年 - 要不要买菜 - 单曲 - 网易云音乐
最后15道入门题,做完这15道,NEWOJ就91道题AC了
目录
一,数根
二,最大值和最小值(I)
三,打印直角三角形
四,最大值和最小值(II)
五,消消乐(一题多解)
字符串操作函数
代码1 s.substr(i, j)
代码2 s.erase(i , j)
代码3 栈
六,按纯度筛选(超限!!)
七,加密数(溢出!!)
总结
P1062 - 数根 - New Online Judge (ecustacm.cn)
卡了好久...思路真的很简单,20行代码的事
1,按字符串输入,转整型
2,整型不用转回字符串再转整型了(麻烦,而且不好实现)(这步想复杂了...)
类似十进制转八进制那样,直接取每一位相加,如果依旧>= 10(即 / 10 != 0),重复这一步
3,注意,构造函数中的return需要赋值给一个变量,而cout才能直接输出
#include
using namespace std;
int number(int x)
{
int y = 0;
while(x) { //注意是x!= 0
y += x % 10;
x /= 10;
}
if(y / 10 == 0) cout<>s;
for(int i = 0; i < s.size(); ++i)
a += s[i] - '0';
number(a);
return 0;
}
24
6
6666
6
9127812749871298471928748124781278471827489214
7
P1063 - 最大值和最小值(I) - New Online Judge (ecustacm.cn)
输入a[n],对a[n]排序得到b[n],b[0]和b[n - 1]即最小值和最大值,再通过遍历将 i 赋值给数组,c[a[i]] = i得到元素对应的下标(需要注意的是,遍历到最大值b[n - 1]即可)然后c[b[0]] - c[b[n - 1]]相减取abs
第一次提交,Ac 90%,因为没考虑比如1 1 1 1的情况,按原代码会输出-1,需要加个max(0, ...)
通过代码
#include
#include //abs
#include //sort()
using namespace std;
int a[10010], b[10010], c[10010];;
int main()
{
int ans, n;
cin>>n;
for(int i = 0; i < n; ++i) {
cin>>a[i];
b[i] = a[i];
}
sort(b, b + n); //从小到大
for(int i = 0; i <= b[n - 1]; ++i) c[a[i]] = i;//元素对应下标
ans = abs(c[b[0]] - c[b[n - 1]]) - 1;
cout<
P1064 - 打印直角三角形 - New Online Judge (ecustacm.cn)
#include
using namespace std;
int main()
{
int n;
while(cin>>n) {
for(int i = 1; i <= n; ++i) {
for(int j = 1; j <= i; ++j)
cout<<"*";
cout<
注意,图形用空行分开
P1065 - 最大值和最小值(II) - New Online Judge (ecustacm.cn)
一开始排序写成sort(a, a + n).....所以Ac 20%,改成sort(a, a + 3)就好了
#include
#include //sort()
#include //memset()
using namespace std;
int a[4]; //保存每只队伍分数
int main()
{
int n, ans = 10000, num;
cin>>n;
for(int i = 1; i <= n; ++i) {
memset(a, 0, sizeof(a)); //每只队伍都要更新a
for(int j = 0; j < 3; ++j) {
cin>>a[j];
}
sort(a, a + 3);
if(ans > a[2] - a[0]) {
ans = min(ans, a[2] - a[0]);
num = i;
}
}
cout<
虽说memset速度慢,但是只有三个数据的话,每次更新一下不影响
给大家展示下一题多解
题目
P1066 - 消消乐 - New Online Judge (ecustacm.cn)
解析
1,s.substr(i)从下标 i 开始到结尾,s.substr(i, j)从下标 i 开始截取 j 个字符(代码1)
2,其实用删除函数更好(代码2)
3,当然用栈也可以(代码3)
第一次发现个小问题,用s.substr()写了删除函数后,发现全局变量在构造函数被修改后,主函数中并没有被改变,苦苦思索了半小时发现,忘记return了......↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓
#include
#include //substr()
using namespace std;
string s;
void cut(string s) //消去一次
{
int r = 0;
for(int i = 1; i < s.size(); ++i) {
if(s[i] == s[i - 1]) r++;
else r = 0;
if(r == 2) {
s = s.substr(0, i - 2) + s.substr(i + 1);
cout<<"函数中全局变量被修改了:"<>s;
cut(s);
cout<<"主函数中输出不变:"<
aaaabbbc
函数中全局变量被修改了:abbbc
主函数中输出不变:aaaabbbc
忘记return浪费半小时
改成这样即可
#include
#include //substr()
using namespace std;
string s;
string cut(string s) //这里要加*, 否则主函数中不变
{
int r = 0;
for(int i = 1; i < s.size(); ++i) {
if(s[i] == s[i - 1]) r++;
else r = 0;
if(r == 2) {
s = s.substr(0, i - 2) + s.substr(i + 1);
cout<<"函数中全局变量被修改了:"<>s;
s = cut(s);
cout<<"主函数中输出不变:"<
aaaabbbc
函数中全局变量被修改了:abbbc
主函数中输出不变:abbbc
首先声明函数时,要声明为string;其次,函数中修改s后,必须return; 最后,主函数中函数的return要赋值给一个变(大坑)
1,截取子串
s.substr(i)从下标 i 开始到结尾,s.substr(i, j)从下标 i 开始截取 j 个字符
2,替换子串
s.replace(i, j, s1)用s1替换s中从下标 i 开始的 j 个字符
3,查找子串
s.find(s1)查找s1在s第一次出现的下标
s.rfind(s1)查找s1在s最后一次出现的下标
4,删除子串
s.erase(i, j)删除从下标 i 开始的 j 个字符
#include
#include //substr()
using namespace std;
string s;
int flag = 1;
string cut(string s)
{
flag = 0;
int r = 0;
for(int i = 1; i < s.size(); ++i) {
if(s[i] == s[i - 1]) r++;
else r = 0;
if(r == 2) {
flag = 1; //可能还存在3个连续的
s = s.substr(0, i - 2) + s.substr(i + 1);
return s;
break;
}
}
return s; //最后一步return s; 别漏了
}
int main()
{
cin>>s;
while(flag) {
s = cut(s);
}
cout<
1,代码第15行,i - 2 和 i + 1 的规律,可以自己在草稿纸罗列acbbbab对应着下标0~6试试
2,cut()函数结尾的return s; 也是个坑
#include
//#include
using namespace std;
string s;
int flag = 1;
string cut(string s)
{
flag = 0;
int r = 0;
for(int i = 1; i < s.size(); ++i) {
if(s[i] == s[i - 1]) r++;
else r = 0;
if(r == 2) {
flag = 1; //可能还存在3个连续的
s.erase(i - 2, 3); //从i - 2开始,删除3个
return s;
break;
}
}
return s; //最后一步return s; 别漏了
}
int main()
{
cin>>s;
while(flag) {
s = cut(s);
}
cout<
也就把代码1第15行换成了 s.erase(i - 2, 3);
s.pop()仅删除栈顶元素,不返回元素,返回void;而s.top()返回栈顶元素,不删除;
s.push()将元素入栈
C++ STL 之stack_buyizhu021的博客-CSDN博客_stack赋值
经过对stack的学习(半小时),再耗费半小时,,还是没完全靠自己敲出来,抄吧
抄着抄着就会了
#include
#include //st.pop(), st.push()
#include //reverse()
using namespace std;
string s;
string cut(string s) //声明全局就别传参了
{
stackst; //记住这种格式
for(int i = 0; i < s.size(); ++i) {
if(st.size() >= 2) { //此处'>'不可少,否则只消去一次
//获取两个元素的值
int a = st.top(); //第一个
st.pop(); //第一个出栈
int b = st.top(); //第二个
st.push(a); //恢复原样
if(s[i] == a && a == b) {//3个元素一样
st.pop();
st.pop();
}
else st.push(s[i]); //不一样就把第三个也入栈
}
else st.push(s[i]); //栈里元素不足2个
}
s = ""; //初始化s为空串
while(!st.empty()) {
s += st.top();
st.pop();
} //栈后进先出,所以字符串反转
reverse(s.begin(), s.end());
return s;
}
int main()
{
cin>>s;
s = cut(s);
cout<
P1067 - 按纯度筛选 - New Online Judge (ecustacm.cn)
1,第一次报错error: can not convert ... to const char*,因为我用strcmp来比较string类的字符串,把string类改成char就好
2,结构体是变量的集合体,切记
3,第二次发现,写的统计字母种类的函数ki()没起作用,原来是数组a[]没有初始化,连0都没有何来++,a[26]改成a[26] = {0},而且设置26为长度的话,遍历时下标要从0开始,否则超限也会输出错误答案
4,第三次!测试样例 + 自己编的包含所有情况的七八组数据,都没问题,但是提交就答案错误。。。what's wrong...
5, 发现问题了,第13行26个桶设置成a[26]会超限,导致你这里结果对,但是系统不给你过,a[26] ----> a[30]就AC了
AC代码
#include
#include //strcmp(),比较字典序;strlen()
#include //sort()
using namespace std;
struct stone
{
int len, kind; //长度和种类
char ss[110];
}s[110];
int ki(char s[]) //得到纯度
{
int kind = 0, a[30] = {0}; //a[30]表示26个桶,设置30防止超限
for(int i = 0; i < strlen(s); ++i)
if(a[s[i] - 'a' + 1] == 0) {
a[s[i] - 'a' + 1] = 1;
kind++;
}
return kind;
}
bool cmp(stone x, stone y) //三种比较规则
{
if(x.kind != y.kind)
return x.kind < y.kind; //返回纯度高的
else if(x.len != y.len)
return x.len > y.len; //返回长度大的
else //如果纯度长度都相等
return strcmp(x.ss, y.ss) < 0; //返回字典序小的
}
int main()
{
int n;
while(cin>>n) {
if(n == 0) break;
for(int i = 0; i < n; ++i) {
cin>>s[i].ss;
s[i].kind = ki(s[i].ss);
s[i].len = strlen(s[i].ss);
}
sort(s, s + n, cmp);
for(int i = 0; i < n; ++i) {
cout<
P1068 - 加密数 - New Online Judge (ecustacm.cn)
要做出这题,首先要了解十进制的二进制表示方法,其次是原码反码补码
(6条消息) 原码、反码、补码详解_独在黑夜_看湖面的博客-CSDN博客_原码反码补码
首先,经过计算 2^7 + 2^8 + 2^16 == 65920,
把每8位作为一个整体,130 = 0 + 2^0 + 2^0 + 2^7
而负数的二进制在计算机中表示为补码,即原码基础上,除符号位外取反并 + 1
-1
原码为10000000 00000000 00000000 00000001
反码为11111111 11111111 11111111 11111110
补码(也就是计算机中形式)11111111 11111111 11111111 11111111
所以-1的加密数为 (1+2+4+8+16+32+64+128) * 4 = 1020
我们要做的是,写个将负数转换为补码的函数(详细步骤看代码注释)
害,整了20个从0到10^9+的数据,包括10个对应负数,跑对拍都没问题。。是系统的问题?
找到原因了!!第5行int c要改long long,因为传入时确实在 int 范围内,但是函数中操作时,可能会取反,比如2^31的二进制取反,由于是无符号整型,会超出int范围(溢出)
Ac代码
#include
#include //memset()
using namespace std;
int a[100];
void binary(long long c, int b[])
{
int flag = 0;
if(c < 0) {
c = -c;
flag = 1;
}
for(int i = 0; i < 32; ++i) { //转二进制
b[i] = c % 2;
c /= 2; //最低位存入数组第一位
}
if(flag) {
for(int i = 0; i < 32; ++i) { //取反,变反码
if(b[i] == 0) b[i] = 1;
else if(b[i] == 1) b[i] = 0;
}
for(int i = 0; i < 32; ++i) { //加1, 变补码
if(b[i] == 0) {b[i] = 1; break;}
else b[i] = 0;
}
}
}
int main()
{
int n;
while(cin>>n) {
memset(a, 0, sizeof(a)); //初始化数组
int ans = 0;
binary(n, a);
int pro = 1;
for(int i = 0; i < 32; ++i) { //计算答案
if(i % 8 == 0) pro = 1; //每8位作为整体
if(a[i] == 1) ans += pro;
pro *= 2;
}
cout<
1,加深了对函数传参,return 和全局变量的了解
2,初步学习了用特例推翻代码,并重构的方法
3,学会跳出思维定势,比如sort(a, a + n)也可能是sort(a + 1, a + n + 1),sort(a, a + 3)......
4,初步学习并运用s.substr(i, j), s.erase(i, j)解决问题(头文件#include
并通过一题多解锻炼解题能力
5,数组超限!老生常谈了,每次最好多设10个长度,多设死不了,少了一定不行
6,int溢出的问题,但这次是初始没溢出,后续操作导致数据超过2^31才溢出的,大坑