题目链接:1:多项式加法
思路:①看到需要合并同系数,排序果断选择用map容器,次数相同合并,那么Key值(First)肯定是选择次数
②输入是系数为负停止,那么第一次输入系数为负只需要continue,第二次结束输入(break)
③输入合法值时查找,如果找到对应次数,系数相加,找不到就插入该元素
代码:
#include
#include
收获:一个新的类型:auto,迭代器类,以后不用写长长的~<...>::iterator
待解答:我自己写的系数相加,查找,插新一直WA,求解答,错误代码放下
while (Test_Time--)
{
map Polynomial; //first-pow,second-Number
int Break_Flag = 0;
while (cin >> Number >> Pow)
{
if (Pow < 0)
{
Break_Flag++;
if (Break_Flag == 1)
continue;
break;
}
it = Polynomial.find(Pow);
if (it != Polynomial.end()) //find it
{
it->second += Number;
if (it->second == 0)
Polynomial.erase(it->first);
}
else
Polynomial.insert(pair(Pow, Number));
}
题目链接:2:字符串插入
思路:①在段极大ACSII码后插入字符串,找第一个最大码值,如果当前字符大于等于下一字符跳出就可以了
②把第一个最大码值后面的元素移动Len位,Len为插入字符串长度
②极端情况:最大值是最后一个,此时跳出查找部分的下标指向 '\0',需要把下标减一
代码:
#include
#include
using namespace std;
#define MAXLENGTH 100
//数据结构与算法mooc(第二章线性表2字符串插入)
int main()
{
char str[MAXLENGTH], substr[MAXLENGTH];
while (cin >> str >> substr)
{
int Len1 = strlen(str), Len2 = strlen(substr);
int Index = 0;
while (str[Index] != '\0')
{
if (str[Index] < str[Index+1])
Index++;
else
break;
}
if (Index == Len1)
Index--;
if (Index != Len1 - 1)
{
for (int i = Len1 - 1; i > Index; i--)
str[i + Len2] = str[i];
}
for (int i = 0; i < Len2; i++)
str[i + Index + 1] = substr[i];
str[Len1 + Len2] = '\0';
cout << str << endl;
}
return 0;
}
题目链接:3:位查询
必备基础:建议看看我写的一篇博,详细讲了位运算,还有对应的例题和应用:位运算总结
#include
using namespace std;
#define MAXSIZE 100005
#define MAX 65535
//数据结构与算法mooc(第二章线性表3位查询)
int Bit_Check(int Number, int pow)
{
Number >>= pow; //右移i个位置
return Number & 1;
}
int main()
{
int Size, Op_Num;
char Instruct;
int Op_index;
int Num[MAXSIZE];
cin >> Size >> Op_Num;
for (int i = 0; i < Size; i++)
cin >> Num[i];
while (Op_Num--)
{
int Statistic = 0; //统计某二进制位为1的数量
cin >> Instruct >> Op_index;
if (Instruct == 'Q')
{
for (int i = 0; i < Size; i++)
Bit_Check(Num[i], Op_index) == 1 ? Statistic++ : Statistic; //该位是1,统计数目加一
cout << Statistic << endl;
}
else
{
for (int i = 0; i < Size; i++)
{
Num[i] += Op_index;
Num[i] = Num[i] > MAX ? Num[i] % (MAX + 1) : Num[i];
}
}
}
return 0;
}
题目链接:4:放苹果
思路(重点讲):将问题降维是解决递归和DP问题的通法,苹果数记为Apple_num,盘子数记为Plate_num
a.苹果数为1或盘子数为1:那么只有一种放法(前者一个苹果放在任一盘,后者全部苹果放一个盘)
b.苹果数小于盘子数:那至少存在Plate_num-Apple_num个空盘子(假设每个盘子放一个苹果),问题等价于Apple_num个苹果放在Apple_num个盘子中,Carry_Apple(Apple_num,Plate_num)=Carry_Apple(Apple_num,Plate_num) ,因为就算每个盘子只放一个苹果最多也只能放Apple_num个盘子。
c.苹果数大于等于盘子数:分两种情况
①每个盘子都有苹果:因为Apple>=Plate嘛,所以先取Plate_num个苹果使得每个盘子有一个苹果,剩余的苹果再进行放置,问题等价于Apple_num-Plate_num个苹果放在Plate_num个盘子 ,Carry_Apple(Apple_num,Plate_num)=Carry_Apple(Apple_num-Plate_num,Plate_num)
②至少有一个盘子没有苹果:去掉这些空的盘子,因为至少一个空嘛,那就先去掉一个空盘,问题等价于Apple_num个苹果放在Plate_num个盘子,Carry_Apple(Apple_num,Plate_num)=Carry_Apple(Apple_num,Plate_num-1)
根据这两种情况,问题等价:
Carry_Apple(Apple_num,Plate_num)=Carry_Apple(Apple_num-Plate_num,Plate_num)+Carry_Apple(Apple_num,Plate_num-1)
(1)递归实现代码
注:递归实现的时候要考虑Apple_num=0的情况,因为当Apple_num-Plate_num有等于0的情况,由c,不难得出如果苹果数等于盘子数,第一种情况每个盘子都有苹果,那只有一种放法(每个盘子一个水果),第二种情况是不变的
问题等价:Carry_Apple(Apple_num,Plate_num)=1+Carry_Apple(Apple_num,Plate_num-1)
所以结束状态中添加苹果数等于0,有一种放法
int Carry_Apple(int Apple_num, int Plate_num)
{
//苹果数量1或者0(考虑递归情况:Apple-Plate=0,那么每个盘子都要有苹果只有一种放置可能)
//盘子数量1,那么所有苹果只能放在一个盘子,1种情况
if (Apple_num == 1 || Apple_num == 0 || Plate_num == 1)
return 1;
//当苹果数量小于盘子树,那至少存在Plate-Apple个空盘,问题等价n个苹果放在n个盘子的情况
else if (Apple_num < Plate_num)
return Carry_Apple(Apple_num, Apple_num);
//苹果数量大于盘子数,总的摆放方式由两种情况确定
//1 每个盘子都有苹果:那么先取plate个苹果使得每个盘子都有一个苹果,问题等价于把剩余苹果分配给plate个盘子
//2 存在没有苹果的盘子,问题等价于把Apple个苹果分给plate-1个盘子(至少有一个空盘)
else //Apple_num>=Plate_num
return Carry_Apple(Apple_num - Plate_num, Plate_num) + Carry_Apple(Apple_num, Plate_num - 1);
}
int main()
{
int Apple_num,Plate_num;
int t;
cin >> t;
while (t--)
{
cin >> Apple_num >> Plate_num;
cout << Carry_Apple(Apple_num, Plate_num) << endl;
}
return 0;
}
(2)DP实现代码
状态转移在上面写得很清楚了
注:DP从1开始,所以考虑需要独立出苹果数等于盘子数
此时:Carry_Apple(Apple_num,Plate_num)=1+Carry_Apple(Apple_num,Plate_num-1)
DP的题为了不超时,不重复计算,先提前打表
int Carry_Apple_DP[100][100] = { 0 };
int MAX_Time = 20;
void DP()
{
for (int Apple = 1; Apple < MAX_Time; Apple++)
{
for (int Plate = 1; Plate < MAX_Time; Plate++)
{
if (Apple == 1 || Plate == 1)
Carry_Apple_DP[Apple][Plate] = 1;
else if (Apple < Plate)
Carry_Apple_DP[Apple][Plate] = Carry_Apple_DP[Apple][Apple];
else if (Apple == Plate)
Carry_Apple_DP[Apple][Plate] = Carry_Apple_DP[Apple][Plate-1] + 1; //plus,添加上这个的原因是Apple-Plate有可能是0,也就是Apple个苹果放Plate个盘子的情况(1),因为动态是从1开始!!!
else //Apple>=Plate
Carry_Apple_DP[Apple][Plate] = Carry_Apple_DP[Apple - Plate][Plate] + Carry_Apple_DP[Apple][Plate - 1];
}
}
}
int main()
{
DP();
int Apple_num, Plate_num;
int T;
cin >> T;
while(T--)
{
cin >> Apple_num >> Plate_num;
cout << Carry_Apple_DP[Apple_num][Plate_num] << endl;
}
}
问题链接:6:大整数乘法
思路:①模拟算术乘法,定一个数的位与另一个数所有位进行逐位相乘,直到定的数所有位遍历完
②逆序保存结果,0位是个位依次类推
实现代码:
#include
#include
using namespace std;
#define MAX_Length 1005
#define Decimal 10
int main()
{
char Mutiply_Result[MAX_Length], Num_A[MAX_Length], Num_B[MAX_Length];
for (int i = 0; i < MAX_Length; i++) //结果字符串数组先初始化为字符0
Mutiply_Result[i] = '0';
cin >> Num_A >> Num_B;
int Len_A = strlen(Num_A), Len_B = strlen(Num_B);
if (Num_A[0] == '0' || Num_B[0] == '0') //其中有一个乘数为0,直接输出0
{
cout << "0" << endl;
return 1;
}
int Begin = 0, Index = 0, Carry_bit = 0;
while (Len_B--)
{
int Temp_Len_A = Len_A;
int Num;
Index = Begin;
Carry_bit = 0; //进位
while (Temp_Len_A--)
{
Num = (Num_B[Len_B] - '0')*(Num_A[Temp_Len_A] - '0') + Carry_bit;
if (Num >= Decimal) //需要进位
{
Carry_bit = (Num - Num % Decimal) / Decimal; //记录下一位的进位
Num %= Decimal; //Num为当前位的进位
}
else
Carry_bit = 0;
Mutiply_Result[Index] += Num; //当前位加上当前位进位Num
if (Mutiply_Result[Index] - '0' >= Decimal) //当前位需要进位
{
Num = Mutiply_Result[Index] - '0'; //记录该位进制数值
Mutiply_Result[Index + 1] += 1; //下一位进1
Mutiply_Result[Index] = Num % Decimal + '0'; //该位取余
}
Index++; //进入下一位
if (Carry_bit&&Temp_Len_A == 0) //如果数A全部与数B的某一位乘完还存在进位,那么当前位的下一位(Index)得加上该进位
{
Mutiply_Result[Index] += Carry_bit;
if (Len_B == 0) //如果此时B所有位都完成乘法,那么当前位才是最高位,下一位才能结束
Index++;
}
}
Begin++;
}
Mutiply_Result[Index+1] = '\0';
for (int i = Index-1 ; i >= 0; i--)
cout << Mutiply_Result[i];
cout << endl;
return 0;
}
自己蠢的地方:要注意定位与另一个数逐位相乘的时候!!!高位是进位(因为结果是逆序的)
还有就是如果乘法上方数(小学乘法了解一下)与下方某位乘完,高位进位还不是0,那么得留下该进位
如果刚好是完成乘法啦,该进位保存之后,Index要记得+1,因为Index指向的是最高位,这时的最高位已经是下一位了。
if (Carry_bit&&Temp_Len_A == 0) //如果数A全部与数B的某一位乘完还存在进位,那么当前位的下一位(Index)得加上该进位
{
Mutiply_Result[Index] += Carry_bit;
if (Len_B == 0) //如果此时B所有位都完成乘法,那么当前位才是最高位,下一位才能结束
Index++;
}