零碎知识的备忘录

这篇博客总结了C++编程中的实用技巧和算法应用,包括next_permutation、nth_element函数,二分查找思路,快读,字符串翻转,快速排序模板,幂运算,输入输出优化,以及位运算优化等,结合洛谷例题进行讲解。

0)在G++不支持%lf,如果G++提交请用%f,如果C++提交请用%lf 。

1)next_permutation()【#include <algorithm>】

作用:求一个排序的下一个排列的函数,可以遍历全排列。

参考案例:Noip普及组2004 火星人

#include<bits/stdc++.h>
using namespace std;
int a[10005],n,m;
int main(){
    scanf("%d%d",&n,&m);
    for(int i=0;i<n;i++)scanf("%d",&a[i]);
    while(m--)    next_permutation(a,a+n);
    for(int i=0;i<n-1;i++)    printf("%d ",a[i]);    printf("%d",a[n-1]);
    return 0;
}

与之完全相反的函数还有prev_permutation(就是一个求一个排序的上一个排列的函数)

一个不错的文章   http://blog.sina.com.cn/s/blog_9f7ea4390101101u.html

2) elelment【#include<algorithm>】

1.nth_element

作用:这个函数主要用来将数组元素中第k小的整数排出来并在数组中就位,随时调用,可谓十分实用。

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

在这里插入图片描述

你会发现,第3大的数3到了该去的位置,并且在3前面的数都比3小,在3后面的数都比3大 

2.max_element / min_element

#include <iostream>
#include <algorithm>
using namespace std;
int main(void)
{
	int a[6] = {5, 3, 2, 6, 1, 4};
	cout<<max_element(a, a+6) - a<<endl;// 输出为3 
	cout<<*max_element(a, a+6)<<endl;//输出为 6 
	cout<<min_element(a, a+6) - a<<endl;// 输出为4 
	cout<<*min_element(a, a+6)<<endl;	 //输出为1 
	return 0; 
}

3)二分思路

如果题目规定了有“最大值最小”或者“最小值最大”的东西,那么这个东西应该就满足二分答案的有界性(显然)和单调性(能看出来)。

例题:洛谷 P2440 木材加工

#include<iostream>
#include<cstdio>
using namespace std;
int n,k,maxx=0,minn=200000000,ans=0;
int a[50000000];
bool judgee(int x)
{
	int alll=0;
	for(int i=1;i<=n;i++)
	{
		alll+=a[i]/x;
	}
	if(alll<k)return false;
	else return true;
 } 
int main()
{
	scanf("%d%d",&n,&k);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		if(minn>a[i]) minn=a[i];
		if(maxx<a[i]) maxx=a[i];
	}
	int mid,l=1,r=maxx;
	while(l<=r)
	{
		mid=(l+r)/2;
		if(judgee(mid))
		{
			ans=mid;
			l=mid+1;
		}
		else r=mid-1;
	}
	printf("%d",ans);
	return 0;
}

4)快读

int read(){//我喜欢快读
    int num = 0;
    char c;
    bool flag = false;
    while ((c = getchar()) == ' ' || c == '\n' || c == '\r');
        if (c == '-') flag = true;
    else
        num = c - '0';
    while (isdigit(c = getchar()))
    num = num * 10 + c - '0';
    return (flag ? -1 : 1) * num;
}

5)reverse 翻转函数

STL里面的反转字符串函数 \color{red}\text{reverse()}reverse()

其格式是: reverse(reverse( 数组名 .begin().begin() ,, 数组名 .end().end() ););

洛谷 P5705 【深基2.例7】数字反转

#include<bits/stdc++.h>   //文件头
using namespace std;
string a;                 //定义字符串
int main() 
{
    cin>>a;               //输入
    reverse(a.begin(),a.end());  //反转
    cout<<a;              //输出
    return 0;             //养成好习惯
}

6)快排模板

void qasort(int l,int r)
{
	int i,j,mid,p;
	i=l;j=r;
	mid=a[(l+r)/2];
	do
	{
		while (a[i]<mid) i++;
		while (a[j]>mid) j--;
		if(i<=j)
		{
			p=a[i];a[i]=a[j];a[j]=p;
			i++;j--;
		}
	}while(i<=j);
	if(l<j) qasort(l,j);
	if(i<r) qasort(i,r);
}

7)求x的y次方 pow(x,y);

包含在头文件math.h之中

8)cin读入一行字符串(且要保存空格)

getline(cin, s);

9)裴蜀定理

gcd(a,b)=ax+by;(存在整数x,y使等式成立,x,y可以是复数)

该表达式可以拓展到无限,gcd(gcd(a,b),c)=ax+by+cz等等;

10)不尽则保留n位小数

题目大意:输入a,b;计算对角线长度与a+b的差,最多保留9位小数。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int a,b;
	double x;
	scanf("%d%d",&a,&b);
	x=sqrt(a*a+b*b);
	cout<<setprecision(9)<<a+b-x;
	return 0;
}

setprecision(n);

11)加快cin输入输出流

ios::sync_with_stdio(false);cin.tie(0);

据说可以达到 scanf 的速度。

12)比较两个字符串

str1.compare(str2);

如果相等则该函数输出为0,不等则输出为-1。

13)数学复制矩阵

/*最大公约数*/inline int gcd(int a, int b) { return b > 0 ? gcd(b, a%b) : a; }
/*最小公倍数*/inline int lcm(int a, int b) { return a * b / gcd(a, b); }
/*平方数*/inline int qpow(int a, int n) { int ans = 1;    while (n) { if (n & 1) { ans *= a; }a *= a; n >>= 1; }return ans; }
/*平方数(结果除模)**/inline int _qpow(int a, int n) { int ans = 1; while (n) { if (n & 1) { ans *= a % mod;    ans %= mod; }a *= a; a %= mod; n >>= 1; }return ans % mod; }
///*快读 */inline int read() { int x = 0, f = 1;    char ch = getchar();    while (ch<'0' || ch>'9') { if (ch == '-') { f = -1; }        ch = getchar(); }    while (ch >= '0'&&ch <= '9') { x = 10 * x + ch - '0';        ch = getchar(); }    return x * f; }

14)快速幂

long long normalPower(long long base, long long power) {
    long long result = 1;
    for (int i = 1; i <= power; i++) {
        result = result * base;
        result = result % 1000;
    }
    return result % 1000;
}
long long int Pow(long long int a, long long int b, long long int c)
{
   if(a==0)
   return 0;
   long long int r = 1, base = a;
   while(b)
   {
     if(b&1)
     {
       r = (r * base) % c;
     }
     base = (base * base) % c;
     b>>=1;
   }
   return r;
}

15)s.substr() 

0. 用途:一种构造string的方法

1. 形式:s.substr(pos, n)

2. 解释:返回一个string,包含s中从pos开始的n个字符的拷贝(pos的默认值是0,n的默认值是s.size() - pos,即不加参数会默认拷贝整个s)

3. 补充:若pos的值超过了string的大小,则substr函数会抛出一个out_of_range异常;若pos+n的值超过了string的大小,则substr会调整n的值,只拷贝到string的末尾

#include<string>
#include<iostream>
using namespace std;
int main()
{
  string s("12345asdf");
  string a = s.substr(5,0);
  cout << a << endl;
}
/*output: 12345*/

16 )string find()函数

#include<cstring>
#include<cstdio>
#include<iostream>
using namespace std;
int main()
{
	/* stage 1 */
	//string中find()返回值是字母在母串中的位置(下标记录),如果没有找到,那么会返回一个特别的标记npos。(返回值可以看成是一个int型的数)
    //find函数返回类型 size_type
    string s("abcdefghijabcde");
    string::size_type position;
    //find 函数 返回jk 在s 中的下标位置
    position = s.find("bc");
    if (position != s.npos)  //如果没找到,返回一个特别的标志c++中用npos表示
    {
        printf("position is : %d\n" ,position);
    }
    else
    {
        printf("Not found the flag\n");
    }
    
    /* stage 2 */ 
    //返回子串出现在母串中的首次出现的位置,和最后一次出现的位置
    string flag="c";
    position = s.find_first_of(flag);
    printf("s.find_first_of(flag) is :%d\n",position);
    position = s.find_last_of(flag);
    printf("s.find_last_of(flag) is :%d\n",position);
    
    /* stage 3 */ 
    //查找某一给定位置后的子串的位置
    //从字符串s 下标5开始,查找字符串b ,返回b 在s 中的下标
    position=s.find("b",5);
    cout<<"s.find(b,5) is : "<<position<<endl;
    
}

17)高效位运算函数高效位运算 __builtin_函数

•__builtin_ffs (unsigned int x)
返回x的最后一位1的是从后向前第几位,比如7368(1110011001000)返回4。
•__builtin_clz (unsigned int x)
返回前导的0的个数。
•__builtin_ctz (unsigned int x)
返回后面的0个个数,和__builtin_clz相对。
•__builtin_popcount (unsigned int x)
返回二进制表示中1的个数。
•__builtin_parity (unsigned int x)
返回x的奇偶校验位,也就是x的1的个数模2的结果。
此外,这些函数都有相应的usigned long和usigned long long版本,
只需要在函数名后面加上l或ll就可以了,比如__builtin_clzll。

18)to_string

#include <iostream>   
#include <string>     
using namespace std;
int main()
{
    string pi = "pi is " + std::to_string(3.1415926);
    string perfect = to_string(1 + 2 + 4 + 7 + 14) + " is a perfect number";
    cout << pi << '\n';
    cout << perfect << '\n';
    system("pause");
    return 0;
}

输出

pi is 3.141593
28 is a perfect number
请按任意键继续. . .

19)1ll

ong long ANS=1LL*num*((1LL)*n*(n-1))/2; ,其中用了1LL;LL其实代表long long,*1LL是为了在计算时,把int类型的变量转化为long long,然后再赋值给long long类型的变量。代码中的ANS的定义为: long long ANS
ANS是long long类型的, ANS=1LL*num*((1LL)*n*(n-1))/2;
不至于后面计算溢出,*1LL 之后类型就转换为long long, num,n定义的是int类型的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值