B1005.继续(3n+1猜想)
**思路:**用哈希表的思想(实际上就是个简单数组,因为没有用到哈希函数),将读入的数字算一个数列出来,然后访问哈希表中的脚标。访问过一次则将表的值改为1. 然后再检索输入的数字里面哪个数字对应的哈希表中的数字是0,把它输出。
需要注意的是:
1.数组的大小一开始开的不够大,挂了两个测试点。(以后往大了开,炸内存了再改小)
2.一个老问题,Vector的erase和for循环时要注意。
例子如下:
for (auto iter = Result.begin(); iter != Result.end(); )//循环和erase一起用要注意
{
if (Hash[*iter] != 0)
{
auto tmp = iter;
iter = Result.erase(tmp);//指针保持没变,相当于中间抽掉一个数
}
else
iter++;
}
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
const int MaxNum = 10000;
int Hash[MaxNum];
vector<int> vec;
vector<int> Result;
void Mark(int K)//根据标记Callatz数组
{
vec.clear();//清除上次使用痕迹
while (K != 1)
{
if (K % 2 == 1)//奇数
K = (3 * K + 1) / 2;
else
K = K / 2;
vec.push_back(K);
}
}
bool cmp(int a ,int b)
{
return a > b;
}
int main()
{
for (int i = 0; i < 10000; i++)//初始化
Hash[i] = 0;
int N, K;
cin >> N;
for (int i = 0; i < N; i++)
{
cin >> K;
Result.push_back(K);//暂存结果
if (Hash[K] != 1)//没有访问过
{
Mark(K);
for (int j = 0; j < vec.size(); j++)//标记此时出现过的数
Hash[vec[j]] = 1;
}
}
/*以上,标记完成*/
sort(Result.begin(), Result.end(),cmp);
int flag = 0;
for (int i = 0; i < Result.size(); i++)
{
if (Hash[Result[i]] == 0)
{
if (flag == 1) cout << " ";
cout << Result[i];
flag = 1;
}
}
return 0;
}
B1006.换个格式输出整数
签到题
/*B1006-换个格式输出*/
#include <iostream>
using namespace std;
int main()
{
int Num;
int Bai, Shi, Ge;
cin >> Num;
Bai = Num / 100;
if (Bai != 0)
for (int i = 0; i < Bai; i++)
cout << "B";
Num = Num % 100;//删掉百位
Shi = Num / 10;
if (Shi != 0)
for (int i = 0; i < Shi; i++)
cout << "S";
Num = Num % 10;//删掉十位
Ge = Num;
for (int i = 1; i <= Ge; i++)
cout << i;
return 0;
}
B1007. 素数对猜想
思路:先写一个IsPrime,然后从i=5开始一直遍历到N,然后判断I 和I-2是否同时为素数。
需要注意的是:
1.注意小于号还有小于等于号的应用情况。
2.IsPrime的写法中,中2开始,到根号a,如果a能被任何一个i整除,则a就不是素数了
/*B1007-s素数对猜想*/
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
const int MaxNumber = 10e5;
bool IsPrime(int a)
{
for (int i = 2; i*i <= a; i++)
if (a % i == 0)
return false;
return true;
}
int main()
{
int Num, i ;
cin >> Num;
if (Num < 5)
{
cout << 0;
return 0;
}
int cnt = 0;
for (i = 5; i <= Num; i++)
{
if (IsPrime(i - 2) && IsPrime(i))
cnt++;
}
cout << cnt;
return 0;
}
B1008.数组循环右移问题
思路: 我不开一个临时数组不会做,完全看题解做的。 题解是用了一个巧妙的规律,先将整个数组倒置,然后导致前M个,再倒置从M到N的数据,最后神奇发现就是右移的结果。
需要注意的是:
1.M大于N的时候,有M%N,因为大于N的倍数的移动都是多余的。
2.用reverse()来实现倒置,在algorithm中
/*B1008-数组元素循环右移问题*/
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
const int MaxN = 101;
int main()
{
int N, M;
cin >> N>> M;
vector<int> vec(N);
for (int i = 0; i < N; i++)
cin >> vec[i];
M = M % N;
if (M != 0)
{
reverse(vec.begin(), vec.begin() + N);
reverse(vec.begin(), vec.begin() + M);
reverse(vec.begin() + M, vec.begin() + N);
}
for (int i = 0; i < N; i++)
{
cout << vec[i];
if (i != N - 1) cout << " ";
}
return 0;
}
B1009.说反话
思路:签到题,直到cin的读取是一个空格一个空格读取的就行。
/*B1009-说反话*/
#include <iostream>
#include <string>
#include <stack>
using namespace std;
int main()
{
string str;
stack<string> S;
while (cin >> str)
S.push(str);
while (!S.empty())
{
cout << S.top();
S.pop();
if (S.size() != 1)
cout << " ";
}
return 0;
}
B1010.一元多项式求导
签到题
/*B1010-一元多项式求导*/
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <cctype>
#include <stack>
using namespace std;
vector<int> result;
int main()
{
int Xishu, Zhishu;
while (cin >> Xishu >> Zhishu)
{
Xishu *= Zhishu;
if (Xishu != 0) result.push_back(Xishu);
Zhishu--;
if (Zhishu >= 0) result.push_back(Zhishu);
}
if (!result.empty())
{
cout << result[0];
for (int i = 1; i<result.size(); i++)
cout << " " << result[i];
}
else
cout << 0 << " " << 0;
return 0;
}
B1011.A+B和C
long long int 可以表示64位(有符号63位)所以直接用longlong就好了不用写大数运算。
/*B1011-A+B和C*/
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <cctype>
#include <stack>
using namespace std;
int main()
{
int Num;
long long A, B, C;
cin >> Num;
for (int i = 0; i < Num; i++)
{
cin >> A >> B >> C;
cout << "Case #" << i + 1 << ":";
if (A + B > C)
cout << " true\n";
else
cout << " false\n";
}
return 0;
}
B1012.数字分类
有个点过不去,不知道为啥
#include <iostream>
#include <vector>
using namespace std;
vector<int> vec;
int main()
{
int Num;
int N;
cin >> N;
for (int i = 0; i < N; i++)
{
cin >> Num;
vec.push_back(Num);
}
int A1 = 0, A2 = 0, A3 = 0, A4Sum = 0, A5 = 0;
int flag = 1;
int A4Num = 0;
int Now;
for (int i = 0; i < vec.size(); i++)
{
Now = vec[i];
if (vec[i] % 10 == 0)
A1 += vec[i];
if (vec[i] % 5 == 1)
{
A2 = A2 + flag * vec[i];
flag = -flag;
}
if (vec[i] % 5 == 2)
A3++;
if (vec[i] % 5 == 3)
{
A4Sum += vec[i];
A4Num++;
}
if (vec[i] % 5 == 4)
if (vec[i] > A5)
A5 = vec[i];
}
double A4;
A4 = (double)A4Sum / (double)A4Num;
if (A1 != 0) cout << A1 << " ";
else cout << "N ";
if (A2 != 0) cout << A2 << " ";
else cout << "N ";
if (A3 != 0) cout << A3 << " ";
else cout << "N ";
if (A4Sum != 0)
printf("%.1lf ", A4);
else
cout << "N ";
if (A5 != 0) cout << A5 ;
else cout << "N";
return 0;
}
B1013.数素数
写个IsPrime然后打印M个素数出来,最后按规格打印就可以了。
#include <iostream>
#include <vector>
using namespace std;
vector<int> Prime;
bool IsPrime(int Num)
{
for (int i = 2; i *i <= Num; i++)
if (Num % i == 0) return false;
return true;
}
int main()
{
int M, N,cnt = 0;
cin >> M>> N;
for (int a = 2; cnt<= N; a++)
{
if (IsPrime(a)) {
Prime.push_back(a);
cnt++;
}
}
int flag = 0;
for (; M <= N; M++)
{
cout << Prime[M - 1];
if (flag != 9) {
if (M != N) {
cout << " ";
flag++;
}
}
else
{
cout << "\n";
flag = 0;
}
}
return 0;
}
B1015.德才论
本题自己写的很乱,故参考了柳神题解。
注意用到了vector数组。其实就是一次性整n个vector放在一个数组中。 具体数据用struct打包起来。 写cmp的时候要注意题意,降序的意思是大的在前,升序才是小的在前。这里错了好几次。还有if里面的大于等于也要注意。
/*B1015*/
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
struct Node
{
int ID;
int de, cai;
};
typedef Node* Student;
vector<Student> V[4];//装有4个vector的数组
int cmp(Student a,Student b)
{
if ((a->cai + a->de) != (b->de + b->cai))
return (a->de + a->cai) > (b->de + b->cai);
else if (a->de != b->de)
return a->de > b->de;//降序,a比较大在前
else
return a->ID < b->ID;//升序,a比较大在后
}
int main()
{
int N, L, H;
cin >> N >> L >> H;
Student stu;
int total = N;
for (int i = 0; i < N; i++)
{
stu = new Node;
cin >> stu->ID >> stu->de >> stu->cai;
if (stu->de < L || stu->cai < L) //注意这里的原题意思
total--;
else if (stu->de >= H && stu->cai >= H) //注意是大于等于
V[0].push_back(stu);
else if (stu->de >= H && stu->cai < H)
V[1].push_back(stu);
else if (stu->de < H && stu->cai < H && stu->de >= stu->cai)
V[2].push_back(stu);
else
V[3].push_back(stu);
}
cout << total<<"\n";
for (int i = 0; i < 4; i++)
{
sort(V[i].begin(), V[i].end(), cmp);//按规则排序
for (int j = 0; j < V[i].size(); j++)
cout << V[i][j]->ID << " " << V[i][j]->de << " " << V[i][j]->cai << "\n";
}
return 0;
}
B1016.部分A+B
1.注意编码问题即可。也就是char 的6如果强制转换会转成54.故用 A - ‘0’ 做快捷又准确。
2.平方用pow()表示,它在 math.h库里面。
/*B1016 部分A+B*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
using namespace std;
int CaculateP(string A,char Da)
{
int cnt = 0,num,sum = 0;
for (int i = 0; i < A.length(); i++)
if (A[i] == Da) cnt++;
if (cnt != 0)
{
//num = (int)Da; //用这种方法会是num = 54 因为6的编码是54
num = Da - '0';
while (cnt != 0)
sum += num * pow(10,--cnt);
return sum;
}
else
return 0;
}
int main()
{
string A, B;
char Da, Db;
int Pa, Pb;
cin >> A >> Da >> B >> Db;
Pa = CaculateP(A, Da);
Pb = CaculateP(B, Db);
cout << Pa + Pb;
return 0;
}
B1017.A除以B
大数运算,写手动除法。先拿左边数第一位除以被除数,然后除数输出,余数乘10加上下一位继续除,一直循环到末尾。
/*B1015*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
using namespace std;
int main()
{
string A;
int B;
cin >> A >> B;
if (A.length() < 17)
{
long long BeiChu;
BeiChu = stoi(A);
cout << BeiChu / B << " " << BeiChu%B;
}
else
{
int tmp = 0;
int len = A.length();
int Shang = (A[0] - '0') / B;
if ((Shang != 0 && len > 1) || len == 1)
cout << Shang;
tmp = (A[0] - '0') % B;
for (int i = 1; i < len; i++)
{
Shang = (tmp * 10 + (A[i] - '0')) / B;
cout << Shang;
tmp = (tmp * 10 + (A[i] - '0')) % B;
}
cout << " " << tmp;
}
return 0;
}
B1018.锤子剪刀布
比较麻烦的模拟题。注意三目运算符的使用方法。 以及最后输出的时候用一个str来极大的简化输出(来自柳神题解),自己写的话多写了好多行if。
但是挂了一个测试点,原因未知。
/*B1018*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
using namespace std;
int main()
{
int N;
cin >> N;
int JW[3] = { 0 };
int YW[3] = { 0 };//0代表B,1代表C,2代表J
char Jia, Yi;
int JWin = 0, YWin = 0;
int Draw= 0;
for (int i = 0; i < N; i++)
{
cin >> Jia >> Yi;
if (Jia == 'C')
{
if (Yi == 'C') Draw++;
if (Yi == 'J')
{
JWin++;
JW[1]++;
}
if (Yi == 'B')
{
YWin++;
YW[0]++;
}
}
if (Jia == 'J')
{
if (Yi == 'J') Draw++;
if (Yi == 'B')
{
JWin++;
JW[2]++;
}
if (Yi == 'C')
{
YWin++;
YW[1]++;
}
}
if (Jia == 'B')
{
if (Yi == 'B') Draw++;
if (Yi == 'C')
{
JWin++;
JW[0]++;
}
if (Yi == 'J')
{
YWin++;
JW[2]++;
}
}
}
cout << JWin << " " << Draw << " " << YWin << "\n";
cout << YWin << " " << Draw << " " << JWin << "\n";
int maxJ = JW[0] < JW[1] ? 1 : 0;
maxJ = JW[maxJ] < JW[2] ? 2 : maxJ;
int maxY = YW[0] < YW[1] ? 1 : 0;
maxY = YW[maxY] < YW[2] ? 2 : maxY;
string str = "BCJ";
cout << str[maxJ] << " " << str[maxY];
return 0;
}
B1019.数字黑洞 (考察str和Int的转化以及位数补全)
1.sort默认按升序排列,小的在前大的在后。如要改变需要自己写cmp。
2.sort返回void。
3.printf("%04d")代表不足4位补全0;
4.用str也可以补全。 str.insert( 补全的起始位置,要补多少个,‘要补的字符’),注意要补的字符是char类型,也就是必须是单引号。
/*B1019*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
using namespace std;
int cmp(char a, char b)
{
return a > b ;//降序,a大时返回1,排序在前
}
int main()
{
int N;
cin >> N;
if (N % 1111 == 0)
{
printf("%d - %d = 0000", N, N);
return 0;
}
string str = to_string(N);
str.insert(0, 4 - str.length(), '0');
do {
int Num1, Num2;
sort(str.begin(), str.end(), cmp);//降序排序
Num1 = stoi(str);
sort(str.begin(), str.end());//升序排序
Num2 = stoi(str);
N = Num1 - Num2;
printf("%04d - %04d = %04d\n", Num1, Num2, N);//printf的补全0
str = to_string(N);
str.insert(0, 4 - str.length(), '0');
} while (str != "6174");
return 0;
}
B1020.月饼
用一个结构体表示月饼的库存,总价和单价。要注意全都要是double类型。然后放到一个vec中,最后排序输出即可。
要注意vec(N)就已经申请好N个位置的空间了。如果是vec是空动态数组。
有个测试点段错误了,原因未知。
/*B1020*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
using namespace std;
struct MoonCake
{
double stock;
double price;
double SinglePrice;
};
int cmp(MoonCake a, MoonCake b)
{
return a.SinglePrice > b.SinglePrice; //单价高的排前面
}
int main()
{
int N,D;
cin >> N >> D;
if (N == 0) return 0;
vector<MoonCake> vec(N);
for (int i = 0; i < N; i++)
{
double stock;
cin >> stock;
vec[i].stock = stock;
}
for (int i = 0; i < N; i++)
{
double price;
cin >> price;
vec[i].price = price;
}
for (int i = 0; i < N; i++)
vec[i].SinglePrice = vec[i].price / vec[i].stock;
sort(vec.begin(), vec.end(), cmp);
int i = 0;
double Result = 0.0;
while (D > 0)
{
if (vec[i].stock <= D)
Result += vec[i].price;
else
Result += vec[i].SinglePrice * D;
D = D - vec[i].stock;
i++;
}
printf("%.2lf",Result);
return 0;
}
B1021.个位数统计
又犯了同样的错误。char的1,如果用(int)强制转化,会转成ascii码的48,用char 的1 -‘0’才是数字1。
/*B1021*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
using namespace std;
int main()
{
string N;
cin >> N;
int Num[10] = {0};
for (int i = 0; i < N.length(); i++)
Num[N[i] - '0']++;
for (int i = 0; i <= 9; i++)
{
if (Num[i] == 0) continue;
else
cout << i << ":" << Num[i]<<"\n";
}
return 0;
}
B1022.D进制的A+B (进制转换)
扩展2进制的转换写法,用原始数据除以D进制,根据每轮的余数推入堆栈,最后输出即可。
注意要排除被除数是0的情况。不然有个测试点挂了。
/*B1022*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
#include <stack>
using namespace std;
int main()
{
int D;
long long int A, B,Sum;
cin >> A >> B>> D;
Sum = A + B;
if (Sum == 0)
{
cout << 0;
return 0;
}
int Yu,Shang = Sum;
stack<int> S;
while (Shang != 0)
{
Yu = Shang % D;
S.push(Yu);
Shang = Shang / D;
}
while(!S.empty())
{
cout<<S.top();
S.pop();
}
return 0;
}
B1023.组个最小数
签到题
/*B1023*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
#include <stack>
using namespace std;
int main()
{
int Num[10] = { 0 };
vector<int> vec;
for (int i = 0; i < 10; i++)
cin >> Num[i];
for (int i = 1; i < 10; i++)//输出第一位
{
if (Num[i] != 0)
{
cout << i;
Num[i]--;
break;
}
}
for (int i = 0; i < 10; i++)
{
if (Num[i] != 0)
{
while (Num[i] != 0)
{
vec.push_back(i);
Num[i]--;
}
}
}
if(vec.size()!= 0)
sort(vec.begin(), vec.end());
for (int i = 0; i < vec.size(); i++)
cout << vec[i];
return 0;
}
B1024.科学计数法
1.substr(起始位置,终止为止);
2.find(‘某个字母’),返回一个Int
3.要注意考虑指数没有底数长的情况,(可是还是挂了测试点)。
/*B1024*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
#include <stack>
using namespace std;
int main()
{
string str;
cin >> str;
if (str[0] == '-') cout << "-";
string Base, Index;
int Epos = str.find('E');
Base = str.substr(1, Epos-1);
Index = str.substr(Epos + 1);
int index = stoi(Index);
if (index < 0)
{
cout << "0.";
for (int i = 0; i < abs(index) - 1; i++)
cout << "0";
for (int i = 0; i < Base.length(); i++)
if (Base[i] != '.')
cout << Base[i];
}
else
{
int len = Base.length();
if (index+2 > len) { //指数较长情况
for (int i = 0; i < len ; i++)
if (Base[i] != '.')
cout << Base[i];
for (int i = 0; i < index - 1; i++)
cout << "0";
}
else//底数较长情况
{
for (int i = 0; i < index +2; i++)
if (Base[i] != '.')
cout << Base[i];
cout << ".";
Base = Base.substr(index + 2);//后半段
cout << Base;
}
}
return 0;
}
B1025.反转链表
建立三个数组分别储存data,next和地址重新排列的位置Relist。注意要引入Sum变量,因为并不是所有的节点都在链表中。
1.排除链表末尾的元素用取余来做。 sum-sum%K
2.遇到栈溢出。因为windows栈大小默认为1M,超过1M就会报错提示栈溢出:stack overflow,把数组放到全局变量里面就没事了
3.reverse反转函数。reverse(开始位置,结束位置)。本题中用begin(list)+K来找每个片段数组的起始位置。
/*B1025*/
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <math.h>
#include <stack>
using namespace std;
int Data[100006], Next[100006], Relist[100006];
//in function main(),array must within size 1mb,so I put them in global
int main()
{
int FirstAdress, N, K;
cin >> FirstAdress >> N >> K;
for (int i = 0; i < N; i++)
{
int tmp;
cin >> tmp;
cin >> Data[tmp] >> Next[tmp];
}
int sum = 0;
while (FirstAdress != -1)//地址位置不等于负一
{
Relist[sum++] = FirstAdress;
FirstAdress = Next[FirstAdress];
}
for (int i = 0; i < (sum - sum % K); i += K)//末尾多余部分(取余结果)不逆转
reverse(begin(Relist)+i , begin(Relist)+i+K);//区间逆转
for (int i = 0; i < sum - 1; i++)
printf("%05d %d %05d\n", Relist[i], Data[Relist[i]], Relist[i + 1]);
printf("%05d %d -1", Relist[sum - 1], Data[Relist[sum - 1]]);
return 0;
}
本文精选了多个算法竞赛题目,包括3n+1猜想、数组循环右移、一元多项式求导等,详细解析了各种算法思路和编程技巧,如哈希表应用、大数运算、链表反转等,适合算法学习者深入理解并实践。
615

被折叠的 条评论
为什么被折叠?



