白坨的知识整理

目录

查找字符串函数

 字符串和数字的相互转化

字符串转数字,使用stoi

数字转字符串,使用c++里的to_string()

二维数组输出问题

 字符串翻转函数

 检查位数,回文数

 快速排序

 归并排序

 高精度乘低精度

 快速幂

输出保留小数点位数

 返回回文数函数

sort函数

 C++获取数组最值

数组或vector最大值最小值

1.求数组的最大值或最小值

2.求数组最大值最小值对应的下标

判断闰年 

一个日期是一年中的第几天

子矩阵的数量

 最大公约数和最小公倍数(一个有趣的写法)

四舍五入保留整数

比较string字符串数组中两个字符串是否一样

cin加速代码

判断闰年

swap

lower_bound( )和upper_bound( )

nth_element输出第K小的数


C++算法题模板

#pragma GCC optimize(3, "Ofast", "inline")

#include <bits/stdc++.h>
using namespace std;

#define endl "\n"
#define IOS ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)

int main()
{
    IOS;
    
    return 0;
}

#pragma GCC optimize(3, "Ofast", "inline")的作用

#pragma GCC optimize 是用来向 GCC 编译器提供特定的优化建议的指令。在这个特定的例子中,#pragma GCC optimize(3, "Ofast", "inline") 是一个优化指令,它将编译器优化级别设置为 3,启用了 Ofast 优化选项,并将函数 inline 化。

  • #pragma GCC optimize(3) 将优化级别设置为 3,这是 GCC 中最高的优化级别。这将启用各种复杂的优化,可能会增加编译时间,但通常会产生最快的可执行代码。
  • "Ofast" 选项启用了一组特定的优化,通常包括了更多的浮点运算优化以及允许某些不符合标准的优化,例如忽略浮点溢出和不精确的算术。
  • "inline" 选项告诉编译器对于适合进行内联的函数,在编译时直接将其内容嵌入调用的地方,而不是通过函数调用的方式执行,以提高执行效率。

需要注意的是,使用这些优化指令可能会使得代码的可移植性下降,因为它们依赖于编译器的特定实现和优化选项。这些指令应该谨慎使用,并且最好只在性能要求非常高且明确知道其行为影响的情况下使用。

在dev中printf和cout混用调试会崩,应避免混用

查找字符串函数

 字符串和数字的相互转化

字符串转数字,使用stoi
string s("12345");
long long a = stoi(s);
cout << a << endl;
数字转字符串,使用c++里的to_string()
long long m = 1234566700;
string str = to_string(m);   //系统提供数字转字符 
cout << str << endl;

二维数组输出问题

 字符串翻转函数

  • reverse(s.begin(),s.end());,结果为 ugouL
  • reverse(s.begin()+1,s.end());,结果为 Lugou
  • reverse(s.begin(),s.end()-2);,结果为 ouLgu

 检查位数,回文数

bool check1(int x)//检查位数
{
	if((1000 <= x && x <= 9999) || (100000 <= x && x <= 999999)) return 0;//不知道&&和||优先级的可以打个括号 
	return 1;
} 
bool check2(int x)//检查是否回文
{
	int a[20], flag = 1;//反正开得下,多开点
	while (x > 0)
	{
		a[flag] = x % 10;
		x /= 10;
		flag++;
	} 
	for (int i = 1; i <= flag / 2; i++)
		if(a[i] != a[flag-i]) return 0;//不符合回文 
	return 1;
} 

 快速排序

#include<bits/stdc++.h>
using namespace std;
const int N=1e2+10;
int n;
int q[N];
void quick_sort(int q[],int l,int r)
{
	if(l>=r)return;
	
	int i=l-1,j=r+1,x=q[l];
	while(i<j)
	{
		do i++;while(q[i]<x);
		do j--;while(q[j]>x);
		if(i<j)
		{
			int t;
			t=q[i];
			q[i]=q[j];
			q[j]=t;
		}
	}
	quick_sort(q,l,j);
	quick_sort(q,j+1,r);
}

int main ()
{
	scanf("%d",&n);
	
	for(int i=0;i<n;i++)scanf("%d",&q[i]);
	
	quick_sort(q,0,n-1);
	
	for(int i=0;i<n;i++)printf("%d ",q[i]);
	return 0;
}

 归并排序

#include<iostream>
using namespace std;

const int N=1000010;
int n;
int q[N],tmp[N];

void merge_sort(int q[],int l,int r)
{
	if(l>=r)return;
	int mid=(l+r)/2;
	
	merge_sort(q,l,mid),merge_sort(q,mid+1,r);
	
	int k=0,i=l,j=mid+1;
	while(i<=mid&&j<=r)
		if(q[i]<=q[j])tmp[k++]=q[i++];
		else tmp[k++]=q[j++];
	while(i<=mid)tmp[k++]=q[i++];
	while(j<=r)tmp[k++]=q[j++];
	
	for(i=l,j=0;i<=r;i++,j++)q[i]=tmp[j];
}
int main()
{
	scanf("%d",&n);
	for(int i=0;i<n;i++)scanf("%d",&q[i]);
	merge_sort(q,0,n-1);
	
	for(int i=0;i<n;i++)printf("%d ",q[i]);
	return 0;
}

 高精度乘低精度

#include<iostream>
#include<vector> 
using namespace std;

vector<int> mul(vector<int>&A,int b)
{
	int t=0;
	vector<int> C;
	for(int i=0;i<A.size()||t;i++)
	{
		if(i<A.size())
		{
			t+=A[i]*b;
		}
		C.push_back(t%10);
		t/=10;
	}
	while (C.size() > 1 && C.back() == 0) C.pop_back();//去掉前导0 
	return C;
}

int main()
{
	string a;
	int b;
	cin>>a>>b;
	vector<int> A ;
	for(int i=a.size()-1;i>=0;i--)
	{
		A.push_back(a[i]-'0');
	}
	auto C=mul(A,b);
	for(int i=C.size()-1;i>=0;i--)cout<<C[i];
	
	return 0;
}

 快速幂

#include<stdio.h>
long long fastpower(long long base,long long power,long long p)
{
	long long result=1;
	while(power>0)
	{
		if(power%2==1)result=result*base%p;
		base=base*base%p;
		power/=2;
	}
	return result;
}
int main ()
{
	long long a,b,p,r;
	scanf("%lld %lld %lld",&a,&b,&p);
	r=fastpower(a,b,p);
	printf("%lld^%lld mod %lld=%lld",a,b,p,r);
	return 0;
}

输出保留小数点位数

printf 支持输出保留小数点位数的数,但是很多人不知道 cout 也可以,但是需要包含头文件 iomanip,代码:

cout << fixed << setprecision(位数) << 值;

 返回回文数函数

int hw(int n)
{
	int t=n;
	int newt=0;
	while(t)
	{
		newt=newt*10+t%10;
		t/=10;	
	}
	return newt;
} 

sort函数

c++标准库里的排序函数的使用方法

I)Sort函数包含在头文件为#include<algorithm>的c++标准库中,调用标准库里的排序方法可以不必知道其内部是如何实现的,只要出现我们想要的结果即可!

II)Sort函数有三个参数:

(1)第一个是要排序的数组的起始地址。

(2)第二个是结束的地址(最后一位要排序的地址)

(3)第三个参数是排序的方法,可以是从大到小也可是从小到大,还可以不写第三个参数,此时默认的排序方法是从小到大排序。

Sortt函数的第三个参数可以用这样的语句告诉程序你所采用的排序原则

less<数据类型>()//从小到大排序

greater<数据类型>()//从大到小排序

#include<iostream>
#include<algorithm>
using namespace std;

int main()
{
 
	int a[10]={9,6,3,8,5,2,7,4,1,0};
 	sort(a,a+10,greater<int>());
 	
 	for(int i=0;i<10;i++)
 	cout<<a[i]<<" ";
	return 0;
}

 利用pair排序

(p1223排队接水部分思路)

     // pair简单介绍
     pair<int, double> p1;  //使用默认构造函数
     p1.first = 1;
     p1.second = 2.5;
     cout << p1.first << ' ' << p1.second << endl;//1 2.5
#include<bits/stdc++.h>
using namespace std;

bool cmp(pair<int,int>a,pair<int,int>b)
{
	return a.second<b.second;
}

int main()
{
	ios::sync_with_stdio(false);
	vector<pair<int,int>> vec;
	int n;
	cin>>n;
	int t;
	for(int i=0;i<n;i++)
	{
		cin>>t;
		vec.push_back({i+1,t});
	}
	sort(vec.begin(),vec.end(),cmp);
	for (auto it = vec.begin();it != vec.end();it++)
    {
        cout <<it->first <<' ';
    }
	return 0;
}

 C++获取数组最值

数组或vector最大值最小值

我们介绍库函数max_element() 及 min_element(),二者返回的都是迭代器
头文件:< algorithm >

1.求数组的最大值或最小值

1)vector容器

 vector<int> nums = {1,2,3,8,0,33,11,9};
 int max_num = *max_element(nums.begin(), nums.end()); //获取最大值
 int min_num = *min_element(nums.begin(), nums.end());//获取最小值

 2)普通数组

int nums[8] = {1,2,3,8,0,33,11,9};
int max_num = *max_element(nums, nums + 8);
int min_num = *min_element(nums, nums + 8);
2.求数组最大值最小值对应的下标

 1)vector容器

 vector<int> nums = {1,2,3,8,0,33,11,9};
 int max_num_index = max_element(nums.begin(), nums.end()) - nums.begin(); //获取最大值对应的下标
 int min_num_index = min_element(nums.begin(), nums.end()) - nums.begin();//获取最小值对应的下标

2)普通数组

int nums[8] = {1,2,3,8,0,33,11,9};
int max_num_index = max_element(nums, nums + 8) - nums; 
int min_num_index = min_element(nums, nums + 8) - nums;

判断闰年 

int fun(int n)   // 判断闰年 yes 1  no 0 
{
	if((n%4==0 && n%100!=0) || n%400==0)	return 1;
	else return 0;
}

一个日期是一年中的第几天

int dayTest(int year,int month,int day) 
{
    int sum, leap;
    switch (month)
    {
        case 1:sum = 0;
            break;
        case 2:sum = 31;
            break;
        case 3:sum = 59;
            break;
        case 4:sum = 90;
            break;
        case 5:sum = 120;
            break;
        case 6:sum = 151;
            break;
        case 7:sum = 181;
            break;
        case 8:sum = 212;
            break;
        case 9:sum = 243;
            break;
        case 10:sum = 273;
            break;
        case 11:sum = 304;
            break;
        case 12:sum = 334;
            break;
        default:printf("data error");
            break;
    }
    sum = sum + day; // 再加上某天的天数
    if (year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)) {// 判断是不是闰年
        leap = 1;
    } else {
        leap = 0;
    }
    if (leap == 1 && month > 2) 
	{
    	sum++;
    }
    return sum;
}

子矩阵/形的数量

有一个 n×m 方格的棋盘,求其方格包含多少正方形、长方形(p2241)

如果我们固定了正方形的右下角(i,j),你能不能算出此时可能的正方形的个数?

显然,此时答案为Min(i,j)

    long long sum=0;// 正方形的个数
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=m;j++)
		{
			sum+=min(i,j);
		}
	}
int fun2(int m,int n)//m,n为行列数,例如m=2,n=1,返回3,矩形总个数
{
	int s=0;
    for (int i = 1; i <= m; i++)
        for (int p = n; p >=1; p--)s += i * p;
    return s;
}

 最大公约数和最小公倍数(一个有趣的写法)

int gcd(int x,int y)
{
 	while(x^=y^=x^=y%=x);return y;
}
int lcm(int x,int y)
{
    return x*y/gcd(x,y);
}

四舍五入保留整数

printf("%d\n", (int)(r + 0.5));

比较string字符串数组中两个字符串是否一样

可以直接string[n]==string[m]

或者可以使用strcmp函数来比较两个字符串是否相同。strcmp函数会返回一个整数值,如果两个字符串相同,则返回0;如果第一个字符串小于第二个字符串,则返回一个负数;如果第一个字符串大于第二个字符串,则返回一个正数。

#include <iostream>
#include <cstring>
using namespace std;

int main() {
    string str[100];

    // 假设字符串数组中有两个字符串 str[0] 和 str[1]
    // 进行比较
    if (strcmp(str[0].c_str(), str[1].c_str()) == 0) {
        cout << "两个字符串相同" << endl;
    } else {
        cout << "两个字符串不相同" << endl;
    }

    return 0;
}

请注意,strcmp函数接受的参数是const char类型,所以我们需要通过c_str()函数将string类型转换为const char类型。

判断闰年

int is_leap_year(int y)
{
	if ((y %4 == 0 && y %100 != 0) || ( y% 400== 0))
	return 1;
	return 0;
}

swap

// 利用指针交换
void swap(int *q,int *p)
{
    int t;
    t=*p;
    *p=*q;
    *q=t;
}

// 无参交换
a = a ^ b;
b = a ^ b;
a = a ^ b;

lower_bound( )和upper_bound( )

lower_bound( )和upper_bound( )都是利用二分查找的方法在一个排好序的数组中进行查找的。

在从小到大的排序数组中,

lower_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num):从数组的begin位置到end-1位置二分查找第一个大于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

在从大到小的排序数组中,重载lower_bound()和upper_bound()

lower_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于或等于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

upper_bound( begin,end,num,greater<type>() ):从数组的begin位置到end-1位置二分查找第一个小于num的数字,找到返回该数字的地址,不存在则返回end。通过返回的地址减去起始地址begin,得到找到数字在数组中的下标。

#include<bits/stdc++.h>
using namespace std;
const int maxn=100000+10;
const int INF=2*int(1e9)+10;
#define LL long long
int cmd(int a,int b){
	return a>b;
}
int main(){
	int num[6]={1,2,4,7,15,34}; 
	sort(num,num+6);                           //按从小到大排序 
	int pos1=lower_bound(num,num+6,7)-num;    //返回数组中第一个大于或等于被查数的下标
	int pos2=upper_bound(num,num+6,7)-num;    //返回数组中第一个大于被查数的下标
	cout<<pos1<<" "<<num[pos1]<<endl;// 3 7 
	cout<<pos2<<" "<<num[pos2]<<endl;// 4 15

	sort(num,num+6,cmd);                      //按从大到小排序
	int pos3=lower_bound(num,num+6,7,greater<int>())-num;  //返回数组中第一个小于或等于被查数的下标
	int pos4=upper_bound(num,num+6,7,greater<int>())-num;  //返回数组中第一个小于被查数的下标 
	cout<<pos3<<" "<<num[pos3]<<endl;// 2 7
	cout<<pos4<<" "<<num[pos4]<<endl;// 3 4
	return 0;	
}

nth_element输出第K小的数

在强大的STL库中存在一个神奇的函数,那就是nth_element,这个函数主要用来将数组元素中第k小的整数排出来并在数组中就位,随时调用,可谓十分实用。

函数语句:nth_element(数组名,数组名+第k小元素,数组名+元素个数);

执行以后数组名[k]即第K小的数,左边的都比它小,右边的都比它大,但不保证有序。

#include<bits/stdc++.h>
using namespace std;
long long n,k,a[5000010];
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++)
        scanf("%d",&a[i]);
    nth_element(a,a+k,a+n);//使第k小整数就位 
    printf("%d",a[k]);//调用第k小整数
}

bitset输出二进制数 

bitset<8> b(12); //长度为8,将12二进制保存在b中,前面位补0

判断一个数是否为2的幂

bool isPowerOfTwo(int n) 
{
    return n > 0 && (n & (n - 1)) == 0;
}

英文字符大小写转换函数

if (ch >= 'a' && ch <= 'z')
    ch = toupper(ch);
else if (ch >= 'A' && ch <= 'Z')
    ch = tolower(ch);

字符串大小比较compare

	int result = str1.compare(str2);
	if (result == 0)
		cout << "str1 equals to str2" << endl;
	else if (result < 0)
		cout << "str1 is less than str2" << endl;
	else
		cout << "str1 is greater than str2" << endl;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值