算法入门
第一天
首先必须提一下万能头#include<bits/stdc++.h>
排列式
题目
题解:
思路是:易知是九个数字,四位数等于两位数位数乘以一个三位数或者一个一位数乘以一个四位数:
#include<bits/stdc++.h>
using namespace std;
int main(){
int acm[9]={1,2,3,4,5,6,7,8,9};
do{
int result = acm[0]*1000 + acm[1]*100 + acm[2]*10 + acm[3];
int one = acm[4];
int four = acm[5]*1000 + acm[6]*100 + acm[7]*10 + acm[8];
int two = acm[4]*10 + acm[5];
int three = acm[6]*100 + acm[7]*10 + acm[8];
if(result == one * four){
printf("%d = %d x %d\n",result,one,four);
}else if(result == two * three){
printf("%d = %d x %d\n",result,two,three);
}
}while(next_permutation(acm,acm+9));
}
收获:
我的想法是穷举,判断是否符合条件,实在是太费时间了,哈哈哈,想了一阵子实在没想出来就看了师傅们的题解,发现了next_permutation(a,a+n)
template<class BidirIt>
bool next_permutation(BidirIt first, BidirIt last)
{
if (first == last) return false;
BidirIt i = last;
if (first == --i) return false;
while (true) {
BidirIt i1, i2;
i1 = i;
if (*--i < *i1) {
i2 = last;
while (!(*i < *--i2))
;
std::iter_swap(i, i2);
std::reverse(i1, last);
return true;
}
if (i == first) {
std::reverse(first, last);
return false;
}
}
}
这个函数是实现对数组a的前n个元素进行全排列,但是进行全排列的数组一定要是有序的(升序),如果不是按照升序排列的,那系统只能找到该序列之后的全排列。
疫情死亡率
题目:
题解:
#include<iostream>
#include<iomanip>
using namespace std;
int main(){
double a,b,c;
cin >> a >>b;
c = (b/a)*100;
cout << fixed <<setprecision(3) << c << "%" << endl;
}
比较简洁的写法:
#include <bits/stdc++.h>
using namespace std;
int main()
{
double a,b;
cin>>a>>b;
printf("%.3f%%",b/a*100);
return 0;
}
收获
==本题中的 fixed 是和 setprecision 联用的==
如果一个数字太大,无法使用 setprecision 指定的有效数位数来打印,则许多系统会以科学表示法的方式打印。
为了防止出现这种情况,可以使用另一个流操作符 fixed,它表示浮点输出应该以固定点或小数点表示法显示:
完成度打卡:
第二天
水题再次来袭:明天星期几?
题目:
题解:
本题正常应该使用条件语句进行判断再进行解决,但是可以使用 bool 类型进行相同效果的操作:
#include <bits/stdc++.h>
using namespace std;
int main(){
int a;
bool b;
cin>>a;
b = 7-a;
cout<<a+1-7*(1-b);
}
a+b
题目:
题解:
#include<bits/stdc++.h>
using namespace std;
int main(){
int a,b;
cin>>a>>b;
cout<<setbase(16)<<a+b;
//printf("%x",a+b);
}
收获:
头文件:
#include
#include
功能:
std::setw
:需要填充多少个字符,默认填充的字符为' '空格
std::setfill
:设置std::setw将填充什么样的字符,如:std::setfill('*')
std::setbase(n)
:将输出数据转换为n进制
std::setprecision()
:控制输出流显示浮点数的数字个数,C++默认的流输出数值有效位是6。
反向输出一个四位数
题目:
题解:
没人说反向四位数是一个数字,不是四个数字啊(狗头)
#include<bits/stdc++.h>
using namespace std;
int main(){
int n;
cin>>n;
while(n!=0){
cout<<n%10;
n/=10;
}
}
组队比赛
题目
题解:
#include <bits/stdc++.h>
using namespace std;
int main(){
int a[3];
int i,j,temp;
int b = 3681;
cin>>a[0]>>a[1]>>a[2]>>a[3];
do{
b = abs((a[0]+a[1])-(a[2]+a[3])) > b ? b : ((a[0]+a[1])-(a[2]+a[3]));
}while(next_permutation(a,a+4));
printf("%d",b);
}
纸牌
题目:
题解:
#include <iostream>
using namespace std;
int main(){
int n;
cin >> n;
if (n%2 == 0){
cout << n/2;
}
if (n%2 == 1){
cout << n/2+1;
}
return 0;
}
解析:(这里参考的是JesCaim师傅的解析过程)
采用对分最小
的原则:原文链接:顺序结构习题-1042纸牌问题题解_牛客博客 (nowcoder.net)
得不到的爱情
题目
题解:
#include<bits/stdc++.h>
using namespace std;
int main(){
long long n,m;
cin>>n>>m;
cout<<n*m-n-m<<endl;
return 0;
}
收获:赛瓦维斯特定理
收获
取整
ceil() 向上取整,往较大的正数靠齐
floor() 向下取整,往较小的正数靠齐
round() 四舍五入
头文件是
不等式:
可以参考OI中你可能会用到的一些不等式及其证明 - -_- - 洛谷博客 (luogu.org)
完成度打卡:
第三天
送分题
题目
题解:
#include<iostream>
#include <algorithm>
using namespace std;
int arr[6];
int main(){
int a,b,c;
cin>>a>>b>>c;
arr[0]=a+b+c;
arr[1]=a*(b+c);
arr[2]=a*b*c;
arr[3]=(a+b)*c;
arr[4]=a*b+c;
arr[5]=a+b*c;
sort(arr,arr+6);
cout<<arr[5];
return 0;
}
收获:
查看相关博客:
sort(first_pointer,first_pointer+n,cmp)
该函数可以给数组,或者链表list、向量排序。
实现原理:sort并不是简单的快速排序,它对普通的快速排序进行了优化,此外,它还结合了插入排序和推排序。系统会根据你的数据形式和数据量自动选择合适的排序方法,这并不是说它每次排序只选择一种方法,它是在一次完整排序中不同的情况选用不同方法,比如给一个数据量较大的数组排序,开始采用快速排序,分段递归,分段之后每一段的数据量达到一个较小值后它就不继续往下递归,而是选择插入排序,如果递归的太深,他会选择推排序。
此函数有3个参数:
参数1:第一个参数是数组的首地址,一般写上数组名就可以,因为数组名是一个指针常量。
参数2:第二个参数相对较好理解,即首地址加上数组的长度n(代表尾地址的下一地址)。
参数3:默认可以不填,如果不填sort会默认按数组升序排序。也就是1,2,3,4排序。也可以自定义一个排序函数,改排序方式为降序什么的,也就是4,3,2,1这样。
更多内容查看:[C++ 中的sort()排序函数用法 - 学习随笔记 - 博客园 (cnblogs.com)](https://www.cnblogs.com/stones-dream/p/10183210.html#:~:text=C%2B%2B 中的sort ()排序函数用法. sort,(first_pointer%2Cfirst_pointer%2Bn%2Ccmp) )
[NOIP2008]ISBN号码
题目:
题解:
#include<bits/stdc++.h>
using namespace std;
int main()
{
string s;
cin >> s;
int ans=0;
int k=1;
for(int i=0;i<=10;i++)
{
if(s[i]=='-')
{
continue;
}
ans+=(s[i]-'0')*(k);
ans%=11;
k++;
}
if(ans==10)
{
if(s[12]=='X') cout << "Right";
else
{
s[12] = 'X';
cout << s;
}
return 0;
}
if(s[12]-'0'==ans)
cout << "Right";
else
{
s[12] = ans+'0';
cout << s;
}
return 0;
}
题解:
本题误会要输入后判断第四个输入值是否为字符串然后再转化,解题的时候十分坎坷,随后就看了烟台大学_贺宜彤这位师傅的题解,豁然开朗,通过一个数组加载输入项,再读取判断,更新数组,秒不可言:dog:!
收获:
做题的时候经常忘记参数范围大小导致无法通过测试案例,今后一定要注意!!!
完成度打卡:
第四天
上下金字塔
题目:
题解:
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
while(cin>>n){
for (int i=1; i<=2*n-1; i++){
for (int j=1; j<=2*n-1; j++){
if(abs(i - n) + abs(j - n) < n) cout << '*';
else cout << ' ' ;
}
cout << endl;
}
}
}
字符金字塔
题目:
题解:
#include<iostream>
using namespace std;
int main()
{
char c;
cin>>c;
int n=c-'A'+1;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n*2-1;j++)
{
int d=abs(n-i)+abs(n-j);
if(d<n) cout<<(char)(c-d);
else cout<<' ';
}
cout<<endl;
}
}
收获:
记住菱形星星的公式与思路,遇到的话可以快速重现代码,保持代码极简化的思想。
完成度打卡
第五天
牛牛学数列6
题目:
题解:
#include<stdio.h>
int main()
{
int n,i;
int a[20]={0,1,1};
scanf("%d",&n);
for(i=3;i<n;i++) a[i]=a[i-3]+2*a[i-2]+a[i-1];
printf("%d",a[i-1]);
}
[NOIP2018]标题统计
题目:
解答:
两种思路,一种是将字符串传递到数组内,一种是直接计量:
//传递数组
#include<bits/stdc++.h>
using namespace std;
string str;
int main()
{
getline(cin,str);
int n = 0;
for(int i = 0; i < str.size(); i++)
{
if(str[i] >= '0' && str[i] <= '9') n++;
else if(str[i] >= 'a' && str[i] <= 'z') n++;
else if(str[i] >= 'A' && str[i] <= 'Z') n++;
}
cout<<n<<endl;
return 0;
}
//直接计量
#include<stdio.h>
int main()
{
char a;
int sum=0;
while(scanf("%c",&a)!=EOF)
{
if(a==' '||a=='\n')
{
continue;
}
sum++;
}
printf("%d\n",sum);
}
收获:
1、当 cin 读取数据时,它会传递并忽略任何前导白色空格字符(空格、制表符或换行符)。一旦它接触到第一个非空格字符即开始阅读,当它读取到下一个空白字符时,它将停止读取。
2、getline 函数如下所示:
getline(cin, inputLine);
其中 cin 是正在读取的输入流,而 inputLine 是接收输入字符串的 string 变量的名称。
此函数可读取整行,包括前导和嵌入的空格,并将其存储在字符串对象中。
有趣的二进制
题目:
题解:
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long n;
while(cin>>n){
bitset<64>s(n);
cout<<s.count()<<endl;
}
return 0;
}
#include <iostream>
using namespace std;
int main (){
unsigned long long int n;
while(cin>>n){
int sum = 0;
while(n){
if(n%2 == 1)
sum++;
n /= 2;
}
cout<<sum<<endl;
sum = 0;
}
return 0;
}
收获:
bitset存储二进制数位,就像一个bool类型的数组一样,但是有空间优化——bitset中的一个元素一般只占1 bit,相当于一个char元素所占空间的八分之一,bitset中的每个元素都能单独被访问,整数类型和布尔数组都能转化成bitset。
bitset的相关函数
.size()
返回大小(位数)
.count()
返回1的个数
.any()
返回是否有1
.none()
返回是否没有1
.set()
全都变成1
.set(p)
将第p + 1位变成1
.set(p, x)
将第p + 1位变成x
.reset()
全都变成0
.reset(p)
将第p + 1位变成0
.flip()
全都取反
.flip(p)
将第p + 1位取反
.to_ulong()
返回它转换为unsigned long的结果,如果超出范围则报错
.to_ullong()
返回它转换为unsigned long long的结果,如果超出范围则报错
.to_string()
返回它转换为string的结果更多可以参考胡小兔的OI博客
[NOIP2006]数列
题目:
题解:
#include<bits/stdc++.h>
using namespace std;
int main() {
long long k,n,sum=0,f=1;
cin>>k>>n;
while(n) {
sum+=(n%2)*f;
f*=k;
n/=2;
}
cout<<sum<<endl;
return 0;
}
只能吃土豆的牛牛
题目:
题解:
#include<bits/stdc++.h>
using namespace std;
int main() {
int t;
cin>>t;
for(int i=1; i<=t; i++) {
long long k,f=1,sum=0;
cin>>k;
while(k) {
sum+=(k%2)*f;
f*=3;
k/=2;
}
cout<<"Case #"<<i<<": "<<sum<<endl;
}
return 0;
}
收获:
数列和只能吃土豆的牛牛都遵从一样的逻辑,以数列为例:
k=3时,数列为:
1,3,4,9,10,12,13..
转换成三进制就是:1,10,11,100,101,110,111..
看起来像是二进制,转化成十进制看看1,2,3,4,5,6,7..
显然,第n项就是n,程序就把这个过程逆回去,先把n转换成二进制,再把它当成K进制,重新转换为十进制.