ACM资料整理
来源:互联网 发布:红外成像目标跟踪算法 编辑:程序博客网 时间:2024/06/09 20:22
一、做题时应注意的地方
1、
做题时考虑输出结果的上、下边际范围,极限值,尤其是在做简单题的时候。
2、
除法能换成乘法的地方,尽量用乘法。
3、
做题时,确保每个句子、每个单词都读懂,读题是做题的根本
4、
处理字符串,千万要保证它以“\0”结尾
5、
进行数组优化,可以在输入的时候就进行向结果靠拢的操作
6、
应用分治处理时
调用函数时,传数组只需打入数组名
传数组内元素如:temp(a[0]);
7、
C语言中大多数头文件在C++中仍然可以用,但推荐在头文件前加一个小写的c字母,然后去掉.h后缀,如ctype.h——cctype
8、
比赛结束前,一定要把正确率稍高点的题都看完
9、
做题时,弄懂题意是前提,普遍最先刷出来的题一定是水题,普遍都做出来的题也一定不难,不要把问题复杂化
10、
注意题目中,测试数据的范围,数组千万别开小了,数据的类型千万别选错了
11、
分治三步法
划分问题:把问题的实例划分成子问题
递归求解:递归解决子题
合并问题:合并子问题的解得到原问题的解
12、
有的题可能用到
scanf("%d,%d",&a,&b);
scanf("%d/%d",&a,&b);
中间必须要输入该字符才可以
13、
浮点数计算有误差,可以用a- dis > 1e-5的形式,
14、
有时题意有说输入时,N>M,但还是比较交换一下确保比较好
15、
对数是处理数论的主要工具
二、零散知识点补漏
1、
^为位运算,表示异或,开关性
如:1010^1111=0101
与(&)、或(|)、非(!)
与集合有关的题可以用位运算:
10110:表示集合{1,2,4}
01100:表示集合{2,3}
位的最后一位为1,表示空集。
全集定义为ALL_BITS=(1<<n)-1
与、或、非,对应集合的交、并、对称差
2、
数组开的很大时,放在main()函数外面
3、
a[x][y]==0;可简写为!a[x][y];
4、
可用如下语句控制空格的输出,第一个输出前没有空格,剩下的输出前都以空格。
for (int i = 0; i < n; i++)
{
if (i != 0) printf(" ");
………………..
}
5、
C++输入带空格的字符串(特别注意,字符串必须用string类型)
举例: #include<iostream>
using namespace std;
int main()
{
string s;
while(getline(cin,s)!=NULL)
{
cout<<s<<endl;
}
return 0;
}
6、
在C语言中,“乘以2”也可以写成“<<1”,意思是“左移一位”。
7、
0、1互换,可应用于标记法
#include<iostream>
usingnamespace std;
int main()
{
int a,q=1;
for(int i=0;i<4;i++)
{
q=!q;
cout<<q<<" ";
}
return 0;
}
输出结果:0 1 0 1
重点:q=!q;
8、
PI=acos(-1.0)
9、
C语言中“%03d”:输出一个数值变量,不足3位前面补0.
10、
不借助变量交换(不推荐用)
int a,b;
scanf("%d%d",&a,&b);
a=a+b;
b=a-b;
a=a-b;
printf("%d%d\n",a,b);
可简化为a^=b^=a^=b;
11、
C语言中输出“%d”字符
用printf("%%d");
puts("%d");
12、
竞赛平台
int范围约为:-2.1*10^9~2.1*10^9
long long范围约为:-9.2*10^18~9.2*10^18
unsigned long long 范围,0~1.8*10^19
注意:定义无符号类型时要加uLL,如:10108uLL;
13、
计算数据类型的范围
#include<limits>
cout<<std::numeric_limits<int>::max()<<endl; //int能表示的最大值
cout<<std::numeric_limits<int>::min()<<endl; //int能表示的最小值
14、
10^-6可编写为1e-6
15、
往数组中输入不定量个数的数
int a[1000],n=0,x;
while(cin>>x)
a[n++]=x;
16、
不限次输入字符
while((c=getchar())!=EOF) //C语言
17、
if(a[i])意思是,如果a[i]==1;
If(!a[i])意思是,如果a[i]==0;
18、
测量string类型长度变量用length(),如:
string t;
inttt=t.length();
19、typedef struct
可用typedef struct{double x,y;}Point;的形式代替结构体,让其更像新生结构类型
20、
string类型的数据相加,就是字符串拼接
21、
定义大数组时尽量用如下形式:
using namespace std;
const int maxn=10000;
int a[maxn];
22、不定长数组:vector
Vercor就是一个不定长数组,例如:若a是一个vector,可以用a.size()读取它的大小,a.resize()改变大小,a.push()_back()向尾部添加元素,a.pop_back()删除最后一个元素,clear()清空,empty()测试是否为空
Vector是一个模板类,用vector<int> a或者vector<double> b来声明一个vector,vector<int>类似于int a[]的整型数组
23、集合:set
set<string>::iterator是迭代器,类似于指针
set迭代器中的元素已从小到大排列好
24、映射:map
就是从键到值得映射,如:
map<string,int> month_name来表示“月份名字到月份编号”的映射,然后用month_name[“July”]=7;来赋值,更多理解详见UVA156
25、数据结构
1.STL的栈在头文件<stack>中,用stack<int> s声明
2.STL的队列在头文件<queue>中,front()取队列首元素,用queue<int> s声明
3.STL的优先队列在<queue>中,优先级高的先出,用priority_queue<int>pq来声明,top()表示优先出队列的元素
5.栈、队列、优先队列都用push()表示入,用pop()表示出。
26、
用优先队列实现一个“个位数大的整数优先级反而小”
用priority_queue<int, vector<int>, cmp >pq的方式定义。下面是cmp的定义:
struct cmp
{
bool operator() (const int a,const int b) const //a的优先级比b小时返回true
{
return a%10>b%10;
}
};
27、
“越小的整数优先级越大到的优先队列”可以写成“ priority_queue<int,vector<int>,greater<int> >pq”
注意:最后的“>”不要写在一起,否则会被认为是“>>”运算符
28、计算一个数转换成二进制中1的个数
#include<iostream>
using namespace std;
int quickOne(int n)
{
int count = 0;
while (n) {
count++;
n= n & (n - 1);
}
return count;
}
int main()
{
char n;
while(cin>>n)
cout<<quickOne(n)<<endl;
return 0;
}
*29、麻烦样例的输入
在int main()中输入,并把文件放入程序所在文件夹,检测样例对错
要加有文件#include<cstdio>
freopen("a.txt","r",stdin);
30、允许输入空格的字符输入,到数组中
char c;
for(int i=1;i<=5;i++)
{
for(int j=1;j<=5;j++)
{
a[i][j]=getchar();
}
getchar(); //注意:还要有一个getchar()用来放回车符
}
31、多边形的三角剖分公式
即使求:在一个凸多边形中,通过若干条互不相交的对角线,把这个多边形划分成了若干个三角形。任务是键盘上输入凸多边形的边数n,求不同划分的方案数f(n)。
a[n+1] 4n-6------- = -------a[n] n
a[4]=2,a[5]=5,a[6]=14,a[7]=42
32、文本结束符(:p>)
括号内的,在用freopen("a.txt","r",stdin);该语句的时候,在txt文档中可用到
33、求逆序对数
举例:
#include<iostream>
using namespace std;
long long cnt;
int a[500010];
int T[500010]; //必须定义在前面
void merge_sort(int* A,long long x,longlong y)
{
if(y-x>1)
{
int m=x+(y-x)/2; //划分
int p=x,q=m,i=x;
merge_sort(A,x,m); //递归求解
merge_sort(A,m,y); //递归求解
while(p<m||q<y)
{
if(q>=y||(p<m&&A[p]<=A[q]))
T[i++]=A[p++]; //从左半数组复制到临时空间,比较后小的赋给虚拟空间
else
{
T[i++]=A[q++]; //从左半数组复制到临时空间,比较后大的赋给虚拟空间
cnt+=m-p;
}
}
for(i=x;i<y;i++)
A[i]=T[i]; //从辅助空间复制回A数组
}
}
int main()
{
intn;
while(cin>>n&&n!=0)
{
cnt=0;
for(int i=0;i<n;i++)
cin>>a[i];
merge_sort(a,0,n);
cout<<cnt<<endl;
}
return0;
}
34、求不大于正整数x的与x互质的正整数的个数,
例如phi(1)=1,phi(2)=1,phi(3)=2,phi(4)=2,phi(5)=4,phi(6)=2等等。
unsigned euler(unsigned x)
{ //就是公式
unsignedi, res=x;
for(i = 2; i < (int)sqrt(x * 1.0) + 1; i++)
if(x%i==0){
res= res / i * (i - 1);
while(x % i == 0) x /= i; // 保证i一定是素数
}
if(x > 1) res = res / x * (x - 1);
returnres;
}
35、
可以通过数学运算,确定某个变量的范围
36、部分背包问题思路
有n个物体,第i个物体的重量为wi,价值为vi。在总重量不超过C的情况下让总价值尽量高。每个物体都可以之取走一部分,价值和重量按比例计算。
思路:应该综合考虑两个因素。贪心的策略是,优先拿“价值除以重量的值”最大的,直到重量和正好为C判断是否是素数
37、判断是否是素数
int prime(int a)
{
int i;
for(i=2;i<sqrt(a);i++)
if(a%i==0)
return 0;
if(i>sqrt(a))
return 1;
注意:调用时用if(prime(a[i])==1)
38、一个数分解成素数形式
#include<iostream>
using namespace std;
int main()
{
int n,n2;
cin>>n;
n2=n;
cout<<n<<"=";
for(int i=2;i<=n;i++)
{
for(;n2%i==0;)
{
n2=n2/i;
cout<<i<<"*";
}
}
cout<<"1";
return 0;
}
39、把结构体,按某一变量标准快速排序
举例:以e为标准,从小到大排序(整个结构体都以e为标准排序好了)
#include<iostream>
#include<algorithm>
using namespace std;
typedef struct{int s,e;}Time;
bool cmp(Time a,Time b)
{
return a.e<b.e;
}
int main()
{
Time t[10005];
for(int i=0;i<5;i++)
cin>>t[i].s>>t[i].e;
sort(t,t+5,cmp);
for(int i=0;i<5;i++)
cout<<t[i].s<<" ";
cout<<endl;
for(int i=0;i<5;i++)
cout<<t[i].e<<" ";
return 0;
}
40、
贪心算法,只考虑当前状态,让它成为最优
三、杂类
1、子集生成
1、增量构造法
#include <iostream>
using namespace std;
int a[20];
/*递归输出n以内所有的子集,其中cur为当前下标,初始值0*/
void print_subset(int n,int* a,int cur){
for(int i=0;i<cur;i++)//每次递归输出当前子集,靠它来最后输出上一层指定的子集
cout<<a[i]<<' ';
cout<<endl;//以行分隔
//找到当前子集首个值,因为按字典顺序输出,所以每次找到最小的元素,cur>0则minElem=a[cur-1]+1,否则为0
intminElem = cur?a[cur-1]+1:0;
//从子集第一个值开始遍历,先不看下面的print_subset(n,a,cur+1);但看这for循环,
//可知是将子集第一个值从头往后依次赋值为minElem-n-1.每次第一个值变化后递归设置下一个值(相当于下一层的第一个值)
for(int i=minElem;i<n;i++){
a[cur]=i;//当前层子集第一个值
//cur+1表示当前层值设置完毕,开始递归下一层,和前面步骤一样。
//到达最后一层结束后return 到上一层,然后i++,a[cur]的值(首元素)改变,又反复递归下一层...
print_subset(n,a,cur+1);
}
}
int main(){
intn ;
while(cin>>n,n){
print_subset(n,a,0);
}
}
1、位向量法
#include <iostream>
using namespace std;
bool b[20]={0};//判断当前每一个节点选中状态
/*递归输出n以内所有的子集,其中b表示该节点是否选中,cur为当前下标,初始值0*/
void print_subset(int n,bool* b,int cur){
//当cur加到n的时候输出该串节点(解答树)的值
if(cur==n){
for (int i=0;i<n;i++){
if(b[i])
cout<<i<<' ';
}
cout<<endl;
return ;
}
b[cur]=true;//该节点设为选中状态
print_subset(n,b,cur+1);//cur+1递归该状态时的下一层节点,循环该操作
b[cur]=false;//该节点设为不选中状态
print_subset(n,b,cur+1);//cur+1递归该状态时的下一层节点,循环该操作
}
int main(){
intn ;
while(cin>>n,n){
print_subset(n,b,0);
}
}
3、二进制法
#include <iostream>
using namespace std;
int n = 4;
void subset()
{
for(int S = 0; S < (1<<n); S++)
{
cout << "S : " << S << " => ";
for(int i = 0; i < n; i++)
{
if(S & (1<<i))
{
cout << i << "";
}
}
cout << endl;
}
}
int main()
{
subset();
}
2、树状数组求逆序数
举例:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <algorithm>
#include <string.h>
using namespace std;
const int maxn=500005;
int n;
int aa[maxn]; //离散化后的数组
int c[maxn]; //树状数组
struct Node
{
int v;
int order;
}in[maxn];
int lowbit(int x)
{
return x&(-x);
}
void update(int t,int value)
{
int i;
for(i=t;i<=n;i+=lowbit(i))
{
c[i]+=value;
}
}
int getsum(int x)
{
int i;
int temp=0;
for(i=x;i>=1;i-=lowbit(i))
{
temp+=c[i];
}
return temp;
}
bool cmp(Node a ,Node b)
{
return a.v<b.v;
}
int main()
{
int i,j;
while(scanf("%d",&n)==1 && n)
{
//离散化
for(i=1;i<=n;i++)
{
scanf("%d",&in[i].v);
in[i].order=i;
}
sort(in+1,in+n+1,cmp);
for(i=1;i<=n;i++) aa[in[i].order]=i;
//树状数组求逆序
memset(c,0,sizeof(c));
long long ans=0;
for(i=1;i<=n;i++)
{
update(aa[i],1);
ans+=i-getsum(aa[i]);
}
cout<<ans<<endl;
}
return 0;
}
四、cmath头文件内函数
math.h 数学函数库,一些数学计算的公式的具体实现是放在math.h里,具体有:
1 、三角函数
doublesin (double);
doublecos (double);
doubletan (double);
2 、反三角函数
doubleasin (double); //结果介于[-PI/2, PI/2]
doubleacos (double); //结果介于[0, PI]
doubleatan (double);//反正切(主值),结果介于[-PI/2,PI/2]
doubleatan2 (double, double); //反正切(整圆值),结果介于
[-PI/2,PI/2]
3 、双曲三角函数
doublesinh (double);
doublecosh (double);
doubletanh (double);
4 、指数与对数
doubleexp (double);
doublepow (double a, double b); //a的b次方
doublesqrt (double);
doublelog (double); //以e为底的对数
double log10 (double);c++ 中自然对数函数:log(N) 以10为底:log10(N)但没有以2为底的函数但是可以用换底公式解决:log2(N)=log10(N)/log10(2)
5 、取整
doubleceil (double); //取上整
doublefloor (double); //取下整
6 、绝对值
doublefabs (double);
7 、准化浮点数
double frexp (doublef, int *p); 标准化浮点数, f = x * 2^p, 已知f
求x, p ( x介于[0.5, 1]) double ldexp (doublex, int p); 与
frexp相反, 已知x,p求f
8 、取整与取余
doublemodf (double,double*);将参数的整数部分通过 指针回传, 返回小数部分
doublefmod(double,double);返回两参数相除的余数
9 、平方根
sqrt
10、计算直角三角形斜边长
用 法:
double hypot(doublex, double y);
举例1:
#include <stdio.h>
#include <math.h>
int main(void)
{
double result;
double x = 3.0;
double y = 4.0;
result = hypot(x, y);
printf("The hypotenuse is: %lf\n",result);
return 0;
}
11、四舍五入
floor(x+0.5); //解释:等于1的区间为[0.5,1.5)
五、cstring头文件内函数(C++字符串函数)
1、strchr函数,查找字符串s中首次出现字符c的位置。
strchr函数原型:extern char *strchr(const char *s,char c);查找字符串s中首次出现字符c的位置。
举例1:
#include<stdio.h>
#include<string.h>
intmain()
{
char a[17];
char *ptr,c='r';
strcpy(a,"This is a string");
ptr=strchr(a,c);
if(ptr)
printf("The character %c is atposition: %s\n",c,ptr);
else
printf("The character was notfound\n");
return 0;
}
输出结果:The character r is at position:ring
2、memset函数,初始化函数
memset:作用是在一段内存块中填充某个给定的值,它是对较大的结构体或数组进行清零操作的一种最快方法
函数原型:void*memset(void *s, int ch, size_t n);
*s为数组名,ch为要填充的数,n为选择填充数组的长度(一般用sizeof(数组名))
举例1:填充字符
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char a[5];
memset(a,'1',5);
for(int i=0;i<5;i++)
cout<<a[i]<<"";
return 0;
}
输出结果:11111
举例2:填充整数0,只能是0
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
int a[5];
memset(a,0,sizeof(a));
for(int i=0;i<5;i++)
cout<<a[i]<<" ";
return 0;
}
输出结果:0 0 0 0 0
3、memmove函数
函数原型:
void *memmove( void* dest, const void* src,size_t count );
功能:
由src所指内存区域复制count个字节到dest所指内存区域,如果src和dest出现重叠,函数会自动处理,返回dest的值。
举例1:将字符串移动
#include <stdio.h>
#include <string.h>
int main(void)
{
char s[]="Golden Global View";
memmove(s,s+7,strlen(s)+1-7);
printf("%s",s);
getchar();
return 0;
}
输出结果:GlobalView
4、memcpy函数
举例1:将s中的字符串复制到字符数组d中
#include<stdio.h>
#include<string.h>
int main()
{
char*s="GoldenGlobalView";
char d[20];
memcpy(d,s,(strlen(s)+1));
printf("%s",d);
getchar();
return 0;
}
输出结果:GoldenGlobalView
举例2:将s中第6个字符开始的6个连续字符复制到d中。(从0开始)
#include<stdio.h>
#include<string.h>
int main()
{
char *s="GoldenGlobalView";
char d[20];
memcpy(d,s+6,6); //从第6个字符(V)开始复制,连续复制6个字符(View)
d[6]='\0';
printf("%s",d);
return 0;
}
输出结果: Global
举例3:复制后覆盖原有部分数据
#include<stdio.h>
#include<string.h>
int main()
{
char src[]="******************************";
char dest[]="abcdefghijlkmnopqrstuvwxyz0123as6";
printf("destinationbeforememcpy:%s\n",dest);
memcpy(dest,src,strlen(src));
printf("destinationaftermemcpy:%s\n",dest);
return 0;
}
输出结果:destinationbefore memcpy:abcdefghijlkmnopqrstuvwxyz0123as6
destination after memcpy: ******************************as6
5、memchr函数,从buf所指内存区域的前count个字节查找字符ch。
函数原型:
extern void *memchr(const void *buf, intch, size_t count);
功能:
从buf所指内存区域的前count个字节查找字符ch。
6、strlen函数(正好是字符串中字符的个数)
举例1:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char*s="GoldenGlobalView";
cout<<strlen(s)<<endl;
return 0;
}
输出结果:16
7、strrev函数(翻转字符串)
举例1:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char s[]="WelcomeToBeijing";
cout<<strrev(s)<<endl;
return 0;
}
输出结果:nijieBoTemocleW
8、strupr(将字符串s1中小写字母转换为大写)
举例1:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char s1[]="abcdef";
char *s2=strupr(s1);
cout<<s2<<endl;
return 0;
}
输出结果:ABCDEF
9、strlwr(将字符串s1中大写字母转换为小写)
举例1:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char s1[]="ABCDEF";
char *s2=strlwr(s1);
cout<<s2<<endl;
return 0;
}
输出结果:abcdef
10、strstr(函数搜索一个字符串在另一个字符串中的第一次出现)
举例1:
#include<stdio.h>
#include<string.h>
int main()
{
char*s="GoldenGlobalView";
char*l="lob";
char*p;
p=strstr(s,l);
if(p)
printf("%s",p);
else
printf("NotFound!");
return 0;
}
输出结果:lobalView
11、strcat函数,字符串剪接(把src所指字符串添加到dest结尾处)
函数原型:
extern char *strcat(char *dest,char*src);
功能:
把src所指字符串添加到dest结尾处(覆盖dest结尾处的'\0')并添加'\0'。
举例1:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char d[20]="GoldenGlobal";
char s[20]="View";
strcat(d,s);
cout<<d<<endl;
return 0;
}
输出结果:GoldenGlobalView
12、strncat函数,剪接n个字符(把src所指字符串的前n个字符添加)
函数原型:
extern char *strncat(char *dest,char*src,int n);
功能:
把src所指字符串的前n个字符添加到dest结尾处(覆盖dest结尾处
的'\0')并添加'\0'。
举例1:
#include<iostream>
#include<cstring>
using namespace std;
int main()
{
char d[20]="GoldenGlobal";
char *s="ViewWinIDELibrary";
strncat(d,s,5);
cout<<d<<endl;
return 0;
}
输出结果:GoldenGlobalViewW
13、strcpy函数,字符串复制
函数声明:
extern char *strcpy(char* dest, constchar *src);
功能:
把从src地址开始且含有NULL结束符的字符串复制到以dest开始的地址空间
注意:
src和dest所指内存区域不可以重叠且dest必须有足够的空间来容纳src的字符串。返回指向dest的指针
14、strncpy函数,复制n个字符
函数原型:
char*strncpy(char*dest,char*src,size_tn);
功能:
复制字符串src中的内容(字符,数字、汉字....)到字符串dest中,复制多少由size_t的值决定,返回指向dest的指针。如果遇到空字符('\0')[1] ,则空字符后面全部为空(字符)
注意:
如:dest[]="Hell99iam!";
src[]="abc\0def";
strncpy(dest,src,5);
此时,dest区域是这样的:'a','b','c','\0','\0','9','i','a','m','!'
注意:\0,\0并不是添加在!的后面。
15、strcspn(顺序搜寻字符串s1与s2中第一个相同的字符)
举例1:
#include <stdio.h >
#include <string.h>
int main()
{
char *s="Golden GlobalView";
char *r="new";
int n;
n=strcspn(s,r);
printf("The first char bothin s1 and s2 is: %c",s[n]);
return 0;
}
输出结果:The first char both in s1 and s2 is: e
16、strcmp(字符串比较函数)
功能:
比较字符串s1和s2。
注意:
当s1<s2时,返回为负数
当s1=s2时,返回值=0
当s1>s2时,返回正数
举例1:
#include<stdio.h>
#include<string.h>
int main()
{ char*s1="Hello,Programmers!";
char*s2="Hello,programmers!";
int r;
r=strcmp(s1,s2);
if(!r)
printf("s1ands2areidentical");
else if(r<0)
printf("s1lessthans2");
else
printf("s1greaterthans2");
return 0;}
输出结果:s1lessthans2
17、strncmp(指定比较的字符串长度函数)
函数原型:
int strncmp(char *str1, char *str2, intmaxlen);
注意:
当s1<s2时,返回为负数
当s1=s2时,返回值=0
当s1>s2时,返回正数
举例1:
#include<string.h>
#include<stdio.h>
int main()
{
char *buf1="aaabbb",*buf2="bbbccc",*buf3="ccc";
int ptr;
ptr=strncmp(buf2,buf1,3);
if(ptr>0)
printf("buffer2 is greater than buffer1\n");
else if(ptr<0)
printf("buffer2 is less than buffer1\n");
ptr=strncmp(buf2,buf3,3);
if(ptr>0)
printf("buffer2 is greater thanbuffer3\n");
else if(ptr<0)
printf("buffer2 is less than buffer3\n");
return 0;
}
输出结果:
buffer2 is greater than buffer1
buffer2 is less than buffer3
18、strtok(分隔字符串函数)
函数原型:
char *strtok(char s[], const char*delim);
功能:
分解字符串为一组字符串。s为要分解的字符串,delim为分隔符字符串。
例如:strtok("abc,def,ghi",","),最后可以分割成为abc def ghi.
举例1:
#include<string.h>
#include<stdio.h>
int main()
{
charinput[16]="abc,d,efg";
char *p;
p=strtok(input,",");
while(p)
{
printf("%s\n",p);
p=strtok(NULL,",");
}
return 0;
}
输出结果:abc
d
efg
19、memcpy(复制字符串函数)
函数原型:
void *memcpy(void *dest, const void *src,size_t n);
功能:
从源src所指的内存地址的起始位置开始拷贝n个字节到目标dest所指的内存地址的起始位置中
举例1:将s中第13个字符开始的4个连续字符复制到d中。(从0开始)
#include<stdio.h>
#include<string.h>
int main()
{
char s[]="GoldenGlobalView";
char d[20];
memcpy(d,s+12,4);//从第13个字符(V)开始复制,连续复制4个字符
d[4]='\0'; //memcpy(d,s+14*sizeof(char),4*sizeof(char));也可
printf("%s\n",d);
return 0;
}
输出结果:View
20、reverse倒置字符串函数
功能:
倒置字符串
举例1:
#include<stdio.h>
#include<string.h>
void reverse(char s[])
{
intc,j,i;
for(i=0,j=strlen(s)-1;i<j;i++,j--) //完成倒置功能,不包括字符串结束符'/0'
{
c=s[i];
s[i]=s[j];
s[j]=c;
}
}
int main() //主函数,用于测试reverse函数的功能
{
chars[]="123456";
reverse(s); //调用倒置函数
printf("%s\n",s); //输出倒置后的字符串
return 0;
}
输出结果:654321
六、cctype头文件内函数
1、isdigit 函数,检查ch是否是数字
函数原型:
int isdigit(int ch);
功能:
检查ch是否是数字(0-9)
函数返回:
是返回1,否则返回0
举例1:
#include <stdio.h>
#include <ctype.h>
int main()
{
char ch1='1';
char ch2='a';
if(isdigit(ch1)!=0)
printf("%c is the ASCII number\n",ch1);
else
printf("%c is not the ASCII number\n",ch1);
if(isdigit(ch2)!=0)
printf("%c is the ASCIInumber\n",ch2);
else
printf("%c is not the ASCII number\n",ch2);
return 0;
}
输出结果:
1 is the ASCII number
a is not the ASCII number
2、isalpha 函数,检查ch是否是字母
函数原型:
int isalpha(int ch);
功能:
检查ch是否是字母
函数返回:
是返回1,否则返回0
举例1:
#include<stdio.h>
#include<ctype.h>
int main()
{
char ch1='*';
char ch2='a';
if(isalnum(ch1)!=0)
printf("%c is the ASCII number or alphebet\n",ch1);
else
printf("%c is not the ASCII number nor alphebet\n",ch1);
if(isalnum(ch2)!=0)
printf("%c is the ASCII number or alphebet\n",ch2);
else
printf("%c is not the ASCII number nor alphebet\n",ch2);
return 0;
}
输出结果:
* is not the ASCII number nor alphabet
a is the ASCII number or alphabet
3、islower 函数,检查ch是否小写字母(a-z)
函数原型:
int islower(int ch);
功能:
检查ch是否小写字母(a-z)
函数返回:
是返回1,否则返回0
4、isupper函数,检测是否是大写字母(A-Z)
函数原型:
extern int isupper(int c);
功能:
判断字符c是否为大写英文字母
举例1:
#include <ctype.h>
#include <stdio.h>
int main()
{
char Test[]="a1B2c3D4";
char *pos;
pos=Test;
while(*pos!=0)
{
if(isupper(*pos))
printf("%c",*pos);
pos++;
}
printf("\n");
return 0;
}
输出结果:
BD
5、ispunct函数,检查参数c是否为标点符号或特殊符号
函数原型:
int ispunct(int c)
功能:
检查参数c是否为标点符号或特殊符号
举例1:
#include<stdio.h>
#include <ctype.h>
int main()
{ char str[]="123c@ #FDsP[e?";
int i;
for(i=0;str[i]!=0;i++)
if(ispunct(str[i])) printf("%c ",str[i]);
return 0;
}
输出结果:@ # [ ?
6、isalnum函数,判断字符变量c是否为字母或数字
函数原型:
extern int isalnum(int c);
功能:
判断字符变量c是否为字母或数字
举例1:
#include<stdio.h>
#include <ctype.h>
int main()
{
int c;
c='a';
printf("%c:%s\n",c,isalnum(c)?"yes":"no");
c='7';
printf("%c:%s\n",c,isalnum(c)?"yes":"no");
c='@';
printf("%c:%s\n",c,isalnum(c)?"yes":"no");
return 0;
}
举例1:
a: yes
7: yes
@: no
7、tolower函数,把字符转换成小写字母,非字母字符不做出处理
函数原型:
int tolower(int c);
功能:
把字符转换成小写字母,非字母字符不做出处理
举例1:
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
int main()
{
string str= "THIS IS A STRING";
for (int i=0; i <str.size(); i++)
str[i] = tolower(str[i]);
cout<<str<<endl;
return 0;
}
输出结果:
this is a string
8、toupper函数,把字符转换成大写字母,非字母字符不做出处理
函数原型:
extern int toupper(int c);
功能:
把字符转换成大写字母,非字母字符不做出处理
举例1:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main()
{
char *s="Hello, World!";
int i;
printf("%s\n",s);
for(i=0;i<strlen(s);i++)
{
putchar(toupper(s[i]));
}
return 0;
}
输出结果:
Hello, World!
HELLO,WORLD!
七、STL模板
1、正、逆序迭代器(正序、逆序输出,按键盘输入顺序)
举例1:
#include<vector>
#include<iostream>
using namespace std;
int main()
{
int a[4];
vector<int> v; //一个存放int元素的向量,一开始里面没有元素
//inta,b,c,d;
for(int i=0;i<4;i++)
{cin>>a[i];
v.push_back(a[i]);} // 将值带入向量
//v.push_back(b);
//v.push_back(c);
//v.push_back(d);
vector<int>::const_iterator i; //常量迭代器
for(i=v.begin();i!=v.end();i++)
cout<<*i<<",";
cout<<endl;
vector<int>::reverse_iterator r; //反向迭代器
for(r=v.rbegin();r!=v.rend();r++)
cout<<*r<<".";
cout<<endl;
vector<int>::iterator j; //非常量迭代器
for(j=v.begin();j!=v.end();j++)
*j=100;
for(i=v.begin();i!=v.end();i++)
cout<<*i<<".";
return 0;
}
输入:1 2 3 4
输出结果:1,2,3,4,
4.3.2.1.
100.100.100.100.
2、set_union(获得两个集合的并集)
举例1:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main ()
{
int first[] = {5,10,15,20,25};
int second[] = {50,40,30,20,10};
vector<int> v(10);
vector<int>::iterator it;
sort (first,first+5);
sort (second,second+5);
it=set_union (first, first+5, second, second+5, v.begin());
cout << "union has " << int(it - v.begin())<< " elements.\n";
return 0;
}
输出结果:union has8 elements.
3、set_intersection(获得两个集合的交集)
举例1:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(int argc, char** argv)
{
int A[] = {5,10,15,20,25};
int B[] = {50,40,30,20,10};
int C[10] = {0};
size_t size_A, size_B, size_C;
vector<int> v;
vector<int>::iterator it;
size_A = sizeof(A)/sizeof(A[0]);
size_B = sizeof(B)/sizeof(B[0]);
size_C = sizeof(C)/sizeof(C[0]);
v.resize(size_A+size_B);
sort (A, A + size_A);
sort (B, B + size_B);
it = set_intersection (A, A+size_A, B, B+size_B, v.begin());
v.resize(it-v.begin());
cout << "The intersection has " << (v.size())<< " elements:" << endl;
for (it=v.begin(); it!=v.end(); ++it)
cout << ' ' << *it;
cout << endl;
if(size_C < v.size())
{
cout << "Array C is too small." << endl;
}
else
{
copy(v.begin(), v.end(), C);
cout << "The array of C is:" << endl;
for (int i = 0; i < v.size(); i ++)
cout << ' ' << C[i];
cout << endl;
}
return 0;
}
输出结果:
The intersection has 2 elements:
1020
The array of C is:
10 20
4、unique(删除所有相邻的重复元素)
头文件:
#include <vector>
功能:
删除所有相邻的重复元素
举例1:
#include <cassert>
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
#include <iterator>
using namespace std;
int main()
{
const int N=11;
int array1[N]={1,2,0,3,3,0,7,7,7,0,8};
vector<int> vector1;
for (int i=0;i<N;++i)
vector1.push_back(array1[i]);
vector<int>::iterator new_end;
new_end=unique(vector1.begin(),vector1.end()); //"删除"相邻的重复元素
assert(vector1.size()==N); //assert相当于if,在#include <cassert>头文件中
vector1.erase(new_end,vector1.end()); //删除(真正的删除)重复的元素
copy(vector1.begin(),vector1.end(),ostream_iterator<int>(cout,""));
cout<<endl;
return 0;
}
输出结果:
1 2 0 3 0 7 0 8
5、insert函数,向迭代器里输入数据
举例1:
#include<iostream>
#include<cstring>
#include<sstream>
#include<set>
using namespace std;
set<string> dict;
int main()
{
string s="aaaaaa",buf;
stringstream ss(s);
while(ss>>buf)
dict.insert(buf);
for(set<string>::iterator it =dict.begin(); it!=dict.end();++it)
cout<<*it<<"\n";
return 0;
}
输出结果:
Aaaaaa
6、deque双端队列,支持首尾两端插入、删除
头文件:
#include <deque>
功能:
支持首尾两端插入、删除
举例1:
#include<iostream>
#include<deque>
using namespace std;
int main()
{
deque<int> c;
c.push_front(1);
c.push_back(2);
c.push_front(3);
for(int i=0;i<c.size();i++)
{
cout<<c[i]<<" ";
}
return 0;
}
输出结果:
3 1 2
方法:
c.assign(beg,end) 将[beg; end)区间中的数据赋值给c。
c.assign(n,elem) 将n个elem的拷贝赋值给c。
c.at(idx) 传回索引idx所指的数据,如果idx越界,抛出out_of_range。
c.back() 返回容器c的最后一个元素的引用。如果c为空,则该操作未定义。
c.begin() 传回迭代器中的第一个数据地址。
c.clear() 移除容器中所有数据。
c.empty() 判断容器是否为空。
c.end() 返回一个迭代器,它指向容器c的最后一个元素的下一位置。
c.erase(pos) 删除pos位置的数据,传回下一个数据的位置。
c.erase(beg,end) 删除[beg,end)区间的数据,传回下一个数据的位置。
c.front() 返回容器c的第一个元素的引用。如果c为空,则该操作为空。
get_allocator 使用构造函数返回一个拷贝。
c.insert(pos,elem) 在pos位置插入一个elem拷贝,传回新数据位置
c.insert(pos,n,elem) 在pos位置插入>n个elem数据。无返回值
c.insert(pos,beg,end) 在pos位置插入在[beg,end)区间的数据。无返回值
c.max_size() 返回容器c可容纳的最多元素个数。
c.pop_back() 删除最后一个数据。
c.pop_front() 删除头部数据。
c.push_back(elem) 在尾部加入一个数据。
c.push_front(elem) 在头部插入一个数据。
c.rbegin() 返回一个逆序迭代器,它指向容器c的最后一个元素。
c.rend() 返回一个逆序迭代器,它指向容器c的第一个元素的前一个位置。
c.resize(num) 重新指定队列的长度。
c.size() 返回容器中实际数据的个数。
c.swap(c2) 交换容器c和c2中的所有元素。
swap(c1,c2) 交换容器c1和c2中的所有元素,和上一方法相似。
7、set集合
举例1:
#include<iostream>
#include<set>
using namespace std;
int main()
{
set<int> set1;
for(int i=0; i<10; ++i)
set1.insert(i);
for(set<int>::iterator p=set1.begin();p!=set1.end();++p)
cout<<*p<<"";
if(set1.insert(3).second)//把3插入到set1中
//插入成功则set1.insert(3).second返回1,否则返回0
//此例中,集中已经有3这个元素了,所以插入将失败
cout<<"set insert success";
else
cout<<"set insert failed";
int a[] = {4, 1, 1, 1, 1, 1, 0, 5, 1, 0};
multiset<int> A;
A.insert(set1.begin(),set1.end());
A.insert(a,a+10);
cout<<endl;
for(multiset<int>::iterator p=A.begin();p!=A.end();++p)
cout<<*p<<" ";
cin.get();
return 0;
}
输出结果:
0123456789 set insert failed
0 0 0 1 1 1 1 1 1 1 2 3 4 4 5 5 6 7 8 9
方法:
begin() 返回指向第一个元素的迭代器
clear() 清除所有元素
count() 返回某个值元素的个数
empty() 如果集合为空,返回true(真)
end() 返回指向最后一个元素之后的迭代器,不是最后一个元素
equal_range() 返回集合中与给定值相等的上下限的两个迭代器
erase() 删除集合中的元素
find() 返回一个指向被查找到元素的迭代器
get_allocator() 返回集合的分配器
insert() 在集合中插入元素
lower_bound() 返回指向大于(或等于)某值的第一个元素的迭代器
key_comp() 返回一个用于元素间值比较的函数
max_size() 返回集合能容纳的元素的最大限值
rbegin() 返回指向集合中最后一个元素的反向迭代器
rend() 返回指向集合中第一个元素的反向迭代器
size() 集合中元素的数目
swap() 交换两个集合变量
upper_bound() 返回大于某个值元素的迭代器
value_comp() 返回一个用于比较元素间的值的函数
八、algorithm头文件内函数
1、sort函数(排序)
举例1:对数组a正序、降序排序
#include<iostream>
#include<algorithm>
using namespace std;
int cmp( const int &a, const int &b)
{
if( a > b )
return 1;
else
return 0;
}
int main()
{
int a[]={3,4,12,1,23,2,1,4};
sort(a,a+8); //是对数组a正序排序
for(int i=0;i<8;i++)
{
cout<<a[i]<<" ";
}
cout<<endl;
sort(a,a+8,cmp); //是对数组a降序排序
for(int i=0;i<8;i++)
{
cout<<a[i]<<" ";
}
return 0;
}
输出结果:
1 1 2 3 4 4 12 23
23 12 4 4 3 2 1 1
另:也可以用该方法从大到小排序
bool cmp(int a,int b)
{
return a>b;
}
2、next_permutation函数(按字典序求下一个的全排列)
举例1:(int型)
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[] = {2,1,3};
while (next_permutation(a, a+3))
{
cout << a[0] << " " << a[1] << "" << a[2] << endl;
}
return 0;
}
输出结果:2 1 3
2 3 1
3 1 2
3 2 1
举例2:(string型)
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
string str;
cin >> str;
sort(str.begin(), str.end());
do
{
cout << str <<" ";
}while (next_permutation(str.begin(), str.end()));
return 0;
}
输入:abc
输出结果:abc acbbac bca cab cba
3、prev_permutation(按字典序求上一个的全排列)
用法:
与next_permutation相同
4、adjacent_find函数,查找两个相邻的等价元素
功能:
查找两个相邻的等价元素
举例1:
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
bool myfunction (int i, int j)
{
return (i==j);
}
int main ()
{
int myints[] = {10,20,30,30,20,10,10,20};
vector<int> myvector (myints,myints+8);
vector<int>::iterator it;
it = adjacent_find (myvector.begin(), myvector.end());
if (it!=myvector.end())
cout << "the first consecutive repeated elements are: "<< *it << endl;
it = adjacent_find (++it, myvector.end(), myfunction);
if (it!=myvector.end())
cout << "the second consecutive repeated elements are: "<< *it << endl;
return 0;
}
5、count函数,在序列中统计某个值出现的次数
举例1:
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[1000]={1,2,3,3,3,4,4,5};
int y=count(a,a+8,3); //(数组名,查询的数组长度,查询个数的数字)
cout<<"number of times "<<y<<endl;
return 0;
}
输出结果:
number of times 3
举例2:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
int ival , searchValue;
vector<int> ivec;
cout<<"Enter some integers(Ctrl+Z to end):"<<endl;
while(cin >> ival)
ivec.push_back(ival);
cin.clear();// 使输入流重新有效
cout<<"Enter an integer you want to search:"<<endl;
cin>>searchValue;
cout<<count(ivec.begin() , ivec.end() , searchValue)
<<" elements in thevector have value "
<<searchValue<<endl;
return 0;
}
6、count_if函数,在序列中统计与某谓词匹配的次数
举例1:
#include <vector>
#include <algorithm>
#include <iostream>
using namespace std;
bool greater10(int value)
{
return value >10;
}
int main()
{
vector<int> v1;
vector<int>::iterator Iter;
v1.push_back(10);
v1.push_back(20);
v1.push_back(10);
v1.push_back(40);
v1.push_back(10);
cout << "v1 : ";
for (Iter = v1.begin(); Iter != v1.end(); Iter++)
cout << *Iter << " ";
cout << endl;
vector<int>::size_type result1 = count_if(v1.begin(), v1.end(), greater10); //count_if算法返回使谓词函数返回条件成立的元素个数
cout << "The number of elements in v1greater than 10 is:"<< result1 << "." <<endl;
return 0;
}
输出结果:
v1 : 10 20 10 40 10
The number of elements in v1 greater than10 is: 2.
7、find函数,查找某个数出现的位置
举例1:
#include<vector>
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int array[10]={10,20,30,40};
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
vector<int>::iterator p;
p=find(v.begin(),v.end(),3); //p=从头找到尾,找3
if(p!=v.end()) //如果p还没到结尾的时候,就找到3了,则输出3
cout<<*p<<endl;
p=find(v.begin(),v.end(),9); //p=从头找到尾,找9
if(p==v.end()) //如果p到最后了,也就是没找到,则输出not found
cout<<"not found "<<endl;
p=find(v.begin()+1,v.end()-2,1);
if(p!=v.end())
cout<<*p<<endl;
int *pp=find(array,array+4,20);
cout<<*pp<<endl;
return 0;
}
输出结果:3
not found
3
20
举例2:
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[]={1,2,2,3,3,4,5};
int x=find(a,a+7,3)-a;
cout<<x+1<<endl;
return 0;
}
输出结果:
4
8、lower_bound(查找大于或者等于x的第一个位置)
头文件:
不用STL模板时
#include<algorithm>
用STL模板时
#include<algorithm>
#include <vector>
功能:
查找大于或者等于x的第一个位置
注意:
必须是先排好序的数组
举例1:
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[100]={1,2,23,33,45,56,123};
int p=lower_bound(a,a+7,35)-a;
cout<<35<<" found at"<<p+1<<endl;
return 0;
}
输出结果:35 foundat 5
举例2:
#include <iostream>
#include <algorithm>
#include <functional>
#include <vector>
using namespace std;
int main()
{
const int VECTOR_SIZE = 8 ;
typedef vector<int> IntVector ;
typedef IntVector::iterator IntVectorIt ;
IntVector Numbers(VECTOR_SIZE) ;
IntVectorIt start, end, it, location ;
Numbers[0] = 4 ;
Numbers[1] = 10;
Numbers[2] = 11 ;
Numbers[3] = 30 ;
Numbers[4] = 69 ;
Numbers[5] = 70 ;
Numbers[6] = 96 ;
Numbers[7] = 100;
start = Numbers.begin() ;
end = Numbers.end() ;
cout << "Numbers { " ;
for(it = start; it != end; it++)
cout << *it << " " ;
cout << " }\n" << endl ;
location = lower_bound(start, end, 30) ;
cout << "First location element 10 can beinserted in Numbers is:"<< location - start+1<< endl ;
return 0;
}
输出结果:
Numbers { 4 10 11 30 69 70 96 100 }
"First location element 10 can beinserted in Numbers is: 4
9、upper_bound(查找大于x的第一个位置)
用法:
与lower_bound()相同
功能:
查找大于x的第一个位置
注意:
必须是先排好序的数组
举例1:
#include<iostream>
#include<algorithm>
using namespace std;
int main()
{
int a[100]={1,2,23,33,45,56,123};
int p=upper_bound(a,a+7,2)-a;
cout<<2<<" found at "<<p+1<<endl;
return 0;
}
输出结果:2 foundat 3
九、iomanip头文件内函数
1、
setiosflags(ios::fixed) 固定的浮点显示
setiosflags(ios::scientific) 指数表示
setiosflags(ios::left) 左对齐
setiosflags(ios::right) 右对齐
setiosflags(ios::skipws) 忽略前导空白
setiosflags(ios::uppercase) 16进制数大写输出
setiosflags(ios::lowercase) 16进制小写输出
setiosflags(ios::showpoint) 强制显示小数点
setiosflags(ios::showpos) 强制显示符号
2、
dec 置基数为10 相当于"%d"
hex 置基数为16 相当于"%X"
oct 置基数为8 相当于"%o"
setfill( 'c' ) 设填充字符为c
setprecision( n ) 设显示有效数字为n位
setw( n ) 设域宽为n个字符
3、
setbase(int n) : 将数字转换为 n 进制.
举例:
cout<<setbase(8)<<setw(5)<<255<<endl;
cout<<setbase(10)<<setw(5)<<255<<endl;
cout<<setbase(16)<<setw(5)<<255<<endl
输出结果:
(空格)(空格)377
(空格)(空格) 255
(空格)(空格)(空格) f f
4、
#include<iomanip>
cout<<setprecision(位数); //控制总位数
cout<<setiosflags(ios::fixed)<<setprecision(位数); //控制小数点后位数
十、cstdlib头文件内函数
1、atoi函数,把字符串转换成整型数
头文件:
#include <stdlib.h>
功能:
把字符串转换成整型数
举例1:
#include<stdlib.h>
#include<stdio.h>
int main()
{
float n;
char const* str="12345.67";
n=atoi(str);
printf("string = %s integer = %f \n",str,n);
return 0;
}
输出结果:
string = 12345.67 integer = 12345.000000
举例2:
#include<stdlib.h>
#include<stdio.h>
int main()
{
char a[]="-100";
char b[]="123";
int c;
c=atoi(a)+atoi(b);
printf("c=%d\n",c);
return 0;
}
输出结果:
c=23
2、atof函数,把字符串转换成浮点数
用法:
与atoi相同
3、atol函数,把字符串转换成长整型数
用法:
与atoi相同
4、itoa函数,把整型数转换成字符串
头文件:
#include <stdlib.h>
功能:;
把整型数转换成字符串
举例1:
#include<stdlib.h>
#include<stdio.h>
int main()
{
int number=123456;
char string[25];
itoa(number,string,10);
printf("integer = %d string = %s\n",number,string);
return 0;
}
输出结果:
integer = 123456string = 123456
5、gcvt函数,把浮点数转换成字符串
功能:
把浮点数转换成字符串
举例1:
#include<iostream>
#include<cstdlib>
using namespace std;
int main()
{
double number=123456.67;
char a[100];
gcvt(number,10,a);
cout<<"integer= "<<number<<" string="<<a<<endl;
return 0;
}
输出结果:
integer= 123457 string= 123456.67
十一、sstream头文件内函数
1、stringstream函数
举例1:可以作为将数字和字符串相互转化的工具
#include<iostream>
#include<cstring>
#include<sstream>
using namespace std;
int main()
{
std::string name("12345");
int age = 27;
stringstream os;
os << age;
os >> name;
// name:27
cout<<name<<endl;
return 0;
}
输出结果;
27
举例2:2.支持char*的输入和输出
#include<iostream>
#include<cstring>
#include<sstream>
using namespace std;
int main()
{
stringstream ss_stream;
char sz_buf[5];
ss_stream << 88888;
ss_stream >> sz_buf; // 直接将数输出到sz_buf字符数组中
for(int i=0;i<5;i++)
cout<<sz_buf[i]<<" ";
cout<<endl;
return 0;
}
输出结果:
8 8 8 8 8
十二、查找
1、快速选择问题(快速查找排序后第K个数),程序优化,应对大量数据时用
问题描述:
输入n个整数和一个正整数k(1<=k<=n),输出这些整数从小到大排序后的第k个(例如,k=1就是最小值)。n<=10*e7
举例:
#include<iostream>
#include<cmath>
#include<cstdlib>
using namespace std;
// 快速选择,平均时间复杂度O(N)
typedef int DataType;
#defineSWAP(x,y) {DataType t=x;x=y;y=t;}
intquickSelect( DataType* A, int beg, int end, int K )
{
DataType pivot;
int i, j;
if ( end - beg + 1 < K ) // error
{
cout<<"error!"<<endl;
exit(0);
}
pivot = A[beg];
i = beg;
j = end + 1;
// 将数组分为小于pivot和大于pivot的两部分
for ( ;; )
{
while(A[++i] < pivot );
while(A[--j] > pivot );
if( i > j ) break;
SWAP(A[i], A[j] );
}
SWAP( A[beg], A[j] );
if ( j - beg == K-1 ) // 如果小于pivot的数目刚好为K-1个,这返回该pivot
returnA[j];
else if ( j - beg >= K ) // 否则,如果小于pivot的数目大于K-1个,则返回该部分中第K大的数
returnquickSelect( A, beg, j-1, K );
else
returnquickSelect( A, j+1, end, K-(j-beg+1) );
}
int main()
{
//freopen("a.txt","r",stdin);
int a[]={34,34,4234,8,445,6481,2387,123,86,514};
cout<<quickSelect(a,0,10,8)<<endl;
return 0;
}
输出结果:
2387
2、二分查找
举例:
#include<iostream>
using namespace std;
int binary(int *a,int n,int key)
{
int l=0,r=n;
while(l<r)
{
int mid=l+(r-l)/2; //避免(l+r)溢出
if(a[mid]==key)
return mid;
if(a[mid]<key)
l=mid+1;
else
r=mid;
}
return -1;
}
int main()
{
int a[]={1,3,4,5,6,7,8};
cout<<binary(a,7,7)+1<<endl; //因为是从0开始的
return 0;
}
十三、几何
1、几何公式
1、三角形:
1. 半周长 P=(a+b+c)/2
2. 面积 S=aHa/2=absin(C)/2=sqrt(P(P-a)(P-b)(P-c))
3. 中线 Ma=sqrt(2(b^2+c^2)-a^2)/2=sqrt(b^2+c^2+2bccos(A))/2
4. 角平分线 Ta=sqrt(bc((b+c)^2-a^2))/(b+c)=2bccos(A/2)/(b+c)
5. 高线 Ha=bsin(C)=csin(B)=sqrt(b^2-((a^2+b^2-c^2)/(2a))^2)
6. 内切圆半径 r=S/P=asin(B/2)sin(C/2)/sin((B+C)/2)
=4Rsin(A/2)sin(B/2)sin(C/2)=sqrt((P-a)(P-b)(P-c)/P)
=Ptan(A/2)tan(B/2)tan(C/2)
7. 外接圆半径 R=abc/(4S)=a/(2sin(A))=b/(2sin(B))=c/(2sin(C))
2、四边形:
D1,D2为对角线,M对角线中点连线,A为对角线夹角
1. a^2+b^2+c^2+d^2=D1^2+D2^2+4M^2
2. S=D1D2sin(A)/2
(以下对圆的内接四边形)
3. ac+bd=D1D2
4. S=sqrt((P-a)(P-b)(P-c)(P-d)),P为半周长
3、正n边形:
R为外接圆半径,r为内切圆半径
1. 中心角 A=2PI/n
2. 内角 C=(n-2)PI/n
3. 边长 a=2sqrt(R^2-r^2)=2Rsin(A/2)=2rtan(A/2)
4. 面积 S=nar/2=nr^2tan(A/2)=nR^2sin(A)/2=na^2/(4tan(A/2))
4、圆:
1. 弧长 l=rA
2. 弦长 a=2sqrt(2hr-h^2)=2rsin(A/2)
3. 弓形高 h=r-sqrt(r^2-a^2/4)=r(1-cos(A/2))=atan(A/4)/2
4. 扇形面积 S1=rl/2=r^2A/2
5. 弓形面积 S2=(rl-a(r-h))/2=r^2(A-sin(A))/2
5、棱柱:
1. 体积 V=Ah,A为底面积,h为高
2. 侧面积 S=lp,l为棱长,p为直截面周长
3. 全面积 T=S+2A
6、棱锥:
1. 体积 V=Ah/3,A为底面积,h为高
(以下对正棱锥)
2. 侧面积 S=lp/2,l为斜高,p为底面周长
3. 全面积 T=S+A
7、棱台:
1. 体积 V=(A1+A2+sqrt(A1A2))h/3,A1.A2为上下底面积,h为高
(以下为正棱台)
2. 侧面积 S=(p1+p2)l/2,p1.p2为上下底面周长,l为斜高
3. 全面积 T=S+A1+A2
8、圆柱:
1. 侧面积 S=2PIrh
2. 全面积 T=2PIr(h+r)
3. 体积 V=PIr^2h
9、圆锥:
1. 母线 l=sqrt(h^2+r^2)
2. 侧面积 S=PIrl
3. 全面积 T=PIr(l+r)
4. 体积 V=PIr^2h/3
10、圆台:
1. 母线 l=sqrt(h^2+(r1-r2)^2)
2. 侧面积 S=PI(r1+r2)l
3. 全面积 T=PIr1(l+r1)+PIr2(l+r2)
4. 体积 V=PI(r1^2+r2^2+r1r2)h/3
11、球:
1. 全面积 T=4PIr^2
2. 体积 V=4PIr^3/3
12、球台:
1. 侧面积 S=2PIrh
2. 全面积 T=PI(2rh+r1^2+r2^2)
3. 体积 V=PIh(3(r1^2+r2^2)+h^2)/6
13、球扇形:
1. 全面积 T=PIr(2h+r0),h为球冠高,r0为球冠底面半径
2. 体积 V=2PIr^2h/3
2、点、线之间的运算
//浮点几何函数库
#include <math.h>
#define eps 1e-8
#define zero(x)(((x)>0?(x):-(x))<eps)
struct point{double x,y;};
struct line{point a,b;};
1、计算cross product (P1-P0)x(P2-P0)
double xmult(point p1,point p2,point p0){
return(p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
double xmult(double x1,double y1,doublex2,double y2,double x0,double y0){
return(x1-x0)*(y2-y0)-(x2-x0)*(y1-y0);
}
2、计算dot product (P1-P0).(P2-P0)
double dmult(point p1,point p2,point p0){
return(p1.x-p0.x)*(p2.x-p0.x)+(p1.y-p0.y)*(p2.y-p0.y);
}
double dmult(double x1,double y1,doublex2,double y2,double x0,double y0){
return(x1-x0)*(x2-x0)+(y1-y0)*(y2-y0);
}
3、两点距离
double distance(point p1,point p2){
returnsqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
double distance(double x1,double y1,doublex2,double y2){
returnsqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
4、判三点共线
int dots_inline(point p1,point p2,pointp3){
returnzero(xmult(p1,p2,p3));
}
int dots_inline(double x1,double y1,doublex2,double y2,double x3,double y3){
returnzero(xmult(x1,y1,x2,y2,x3,y3));
}
5、判点是否在线段上,包括端点
int dot_online_in(point p,line l){
returnzero(xmult(p,l.a,l.b))&&(l.a.x-p.x)*(l.b.x-p.x)<eps&&(l.a.y-p.y)*(l.b.y-p.y)<eps;
}
int dot_online_in(point p,point l1,pointl2){
returnzero(xmult(p,l1,l2))&&(l1.x-p.x)*(l2.x-p.x)<eps&&(l1.y-p.y)*(l2.y-p.y)<eps;
}
int dot_online_in(double x,double y,doublex1,double y1,double x2,double y2){
returnzero(xmult(x,y,x1,y1,x2,y2))&&(x1-x)*(x2-x)<eps&&(y1-y)*(y2-y)<eps;
}
6、判点是否在线段上,不包括端点
int dot_online_ex(point p,line l){
returndot_online_in(p,l)&&(!zero(p.x-l.a.x)||!zero(p.y-l.a.y))&&(!zero(p.x-l.b.x)||!zero(p.y-l.b.y));
}
int dot_online_ex(point p,point l1,pointl2){
returndot_online_in(p,l1,l2)&&(!zero(p.x-l1.x)||!zero(p.y-l1.y))&&(!zero(p.x-l2.x)||!zero(p.y-l2.y));
}
int dot_online_ex(double x,double y,doublex1,double y1,double x2,double y2){
returndot_online_in(x,y,x1,y1,x2,y2)&&(!zero(x-x1)||!zero(y-y1))&&(!zero(x-x2)||!zero(y-y2));
}
7、判两点在线段同侧,点在线段上返回0
int same_side(point p1,point p2,line l){
returnxmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)>eps;
}
int same_side(point p1,point p2,pointl1,point l2){
returnxmult(l1,p1,l2)*xmult(l1,p2,l2)>eps;
}
8、判两点在线段异侧,点在线段上返回0
int opposite_side(point p1,point p2,linel){
returnxmult(l.a,p1,l.b)*xmult(l.a,p2,l.b)<-eps;
}
int opposite_side(point p1,point p2,pointl1,point l2){
returnxmult(l1,p1,l2)*xmult(l1,p2,l2)<-eps;
}
9、判两直线平行
int parallel(line u,line v){
returnzero((u.a.x-u.b.x)*(v.a.y-v.b.y)-(v.a.x-v.b.x)*(u.a.y-u.b.y));
}
int parallel(point u1,point u2,pointv1,point v2){
returnzero((u1.x-u2.x)*(v1.y-v2.y)-(v1.x-v2.x)*(u1.y-u2.y));
}
10、判两直线垂直
int perpendicular(line u,line v){
returnzero((u.a.x-u.b.x)*(v.a.x-v.b.x)+(u.a.y-u.b.y)*(v.a.y-v.b.y));
}
int perpendicular(point u1,point u2,pointv1,point v2){
returnzero((u1.x-u2.x)*(v1.x-v2.x)+(u1.y-u2.y)*(v1.y-v2.y));
}
11、判两线段相交,包括端点和部分重合
int intersect_in(line u,line v){
if(!dots_inline(u.a,u.b,v.a)||!dots_inline(u.a,u.b,v.b))
return!same_side(u.a,u.b,v)&&!same_side(v.a,v.b,u);
returndot_online_in(u.a,v)||dot_online_in(u.b,v)||dot_online_in(v.a,u)||dot_online_in(v.b,u);
}
int intersect_in(point u1,point u2,pointv1,point v2){
if(!dots_inline(u1,u2,v1)||!dots_inline(u1,u2,v2))
return!same_side(u1,u2,v1,v2)&&!same_side(v1,v2,u1,u2);
returndot_online_in(u1,v1,v2)||dot_online_in(u2,v1,v2)||dot_online_in(v1,u1,u2)||dot_online_in(v2,u1,u2);
}
12、判两线段相交,不包括端点和部分重合
int intersect_ex(line u,line v){
returnopposite_side(u.a,u.b,v)&&opposite_side(v.a,v.b,u);
}
int intersect_ex(point u1,point u2,pointv1,point v2){
returnopposite_side(u1,u2,v1,v2)&&opposite_side(v1,v2,u1,u2);
}
13、计算两直线交点,注意事先判断直线是否平行!
//线段交点请另外判线段相交(同时还是要判断是否平行!)
point intersection(line u,line v){
pointret=u.a;
doublet=((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x))
/((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x));
ret.x+=(u.b.x-u.a.x)*t;
ret.y+=(u.b.y-u.a.y)*t;
returnret;
}
point intersection(point u1,point u2,pointv1,point v2){
pointret=u1;
doublet=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))
/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
ret.x+=(u2.x-u1.x)*t;
ret.y+=(u2.y-u1.y)*t;
returnret;
}
14、点到直线上的最近点
point ptoline(point p,line l){
pointt=p;
t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;
returnintersection(p,t,l.a,l.b);
}
point ptoline(point p,point l1,point l2){
pointt=p;
t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;
returnintersection(p,t,l1,l2);
}
15、点到直线距离
double disptoline(point p,line l){
returnfabs(xmult(p,l.a,l.b))/distance(l.a,l.b);
}
double disptoline(point p,point l1,pointl2){
returnfabs(xmult(p,l1,l2))/distance(l1,l2);
}
double disptoline(double x,double y,doublex1,double y1,double x2,double y2){
returnfabs(xmult(x,y,x1,y1,x2,y2))/distance(x1,y1,x2,y2);
}
16、点到线段上的最近点
point ptoseg(point p,line l){
pointt=p;
t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;
if(xmult(l.a,t,p)*xmult(l.b,t,p)>eps)
returndistance(p,l.a)<distance(p,l.b)?l.a:l.b;
returnintersection(p,t,l.a,l.b);
}
point ptoseg(point p,point l1,point l2){
pointt=p;
t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;
if(xmult(l1,t,p)*xmult(l2,t,p)>eps)
returndistance(p,l1)<distance(p,l2)?l1:l2;
returnintersection(p,t,l1,l2);
}
17、点到线段距离
double disptoseg(point p,line l){
pointt=p;
t.x+=l.a.y-l.b.y,t.y+=l.b.x-l.a.x;
if(xmult(l.a,t,p)*xmult(l.b,t,p)>eps)
returndistance(p,l.a)<distance(p,l.b)?distance(p,l.a):distance(p,l.b);
returnfabs(xmult(p,l.a,l.b))/distance(l.a,l.b);
}
double disptoseg(point p,point l1,pointl2){
pointt=p;
t.x+=l1.y-l2.y,t.y+=l2.x-l1.x;
if(xmult(l1,t,p)*xmult(l2,t,p)>eps)
returndistance(p,l1)<distance(p,l2)?distance(p,l1):distance(p,l2);
returnfabs(xmult(p,l1,l2))/distance(l1,l2);
}
18、矢量V以P为顶点逆时针旋转angle并放大scale倍
point rotate(point v,point p,doubleangle,double scale){
pointret=p;
v.x-=p.x,v.y-=p.y;
p.x=scale*cos(angle);
p.y=scale*sin(angle);
ret.x+=v.x*p.x-v.y*p.y;
ret.y+=v.x*p.y+v.y*p.x;
returnret;
}
3、凸边形面积
#include <math.h>
struct point{double x,y;};
1、计算cross product (P1-P0)x(P2-P0)
double xmult(point p1,point p2,point p0){
return(p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
double xmult(double x1,double y1,doublex2,double y2,double x0,double y0){
return(x1-x0)*(y2-y0)-(x2-x0)*(y1-y0);
}
2、计算三角形面积,输入三顶点
double area_triangle(point p1,pointp2,point p3){
returnfabs(xmult(p1,p2,p3))/2;
}
double area_triangle(double x1,doubley1,double x2,double y2,double x3,double y3){
returnfabs(xmult(x1,y1,x2,y2,x3,y3))/2;
}
3、计算三角形面积,输入三边长
double area_triangle(double a,doubleb,double c){
doubles=(a+b+c)/2;
returnsqrt(s*(s-a)*(s-b)*(s-c));
}
4、计算多边形面积,顶点按顺时针或逆时针给出
double area_polygon(int n,point* p){
doubles1=0,s2=0;
inti;
for(i=0;i<n;i++)
s1+=p[(i+1)%n].y*p[i].x,s2+=p[(i+1)%n].y*p[(i+2)%n].x;
returnfabs(s1-s2)/2;
}
4、球面
#include <math.h>
const double pi=acos(-1);
1、计算圆心角lat表示纬度,-90<=w<=90,lng表示经度
//返回两点所在大圆劣弧对应圆心角,0<=angle<=pi
double angle(double lng1,double lat1,doublelng2,double lat2){
doubledlng=fabs(lng1-lng2)*pi/180;
while(dlng>=pi+pi)
dlng-=pi+pi;
if(dlng>pi)
dlng=pi+pi-dlng;
lat1*=pi/180,lat2*=pi/180;
returnacos(cos(lat1)*cos(lat2)*cos(dlng)+sin(lat1)*sin(lat2));
}
2、计算距离,r为球半径
double line_dist(double r,doublelng1,double lat1,double lng2,double lat2){
doubledlng=fabs(lng1-lng2)*pi/180;
while(dlng>=pi+pi)
dlng-=pi+pi;
if(dlng>pi)
dlng=pi+pi-dlng;
lat1*=pi/180,lat2*=pi/180;
returnr*sqrt(2-2*(cos(lat1)*cos(lat2)*cos(dlng)+sin(lat1)*sin(lat2)));
}
3、计算球面距离,r为球半径
inline double sphere_dist(double r,doublelng1,double lat1,double lng2,double lat2){
returnr*angle(lng1,lat1,lng2,lat2);
}
5、三角形
#include <math.h>
struct point{double x,y;};
struct line{point a,b;};
double distance(point p1,point p2){
returnsqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
point intersection(line u,line v){
pointret=u.a;
doublet=((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x))
/((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x));
ret.x+=(u.b.x-u.a.x)*t;
ret.y+=(u.b.y-u.a.y)*t;
returnret;
}
1、外心
point circumcenter(point a,point b,pointc){
lineu,v;
u.a.x=(a.x+b.x)/2;
u.a.y=(a.y+b.y)/2;
u.b.x=u.a.x-a.y+b.y;
u.b.y=u.a.y+a.x-b.x;
v.a.x=(a.x+c.x)/2;
v.a.y=(a.y+c.y)/2;
v.b.x=v.a.x-a.y+c.y;
v.b.y=v.a.y+a.x-c.x;
returnintersection(u,v);
}
2、内心
point incenter(point a,point b,point c){
lineu,v;
doublem,n;
u.a=a;
m=atan2(b.y-a.y,b.x-a.x);
n=atan2(c.y-a.y,c.x-a.x);
u.b.x=u.a.x+cos((m+n)/2);
u.b.y=u.a.y+sin((m+n)/2);
v.a=b;
m=atan2(a.y-b.y,a.x-b.x);
n=atan2(c.y-b.y,c.x-b.x);
v.b.x=v.a.x+cos((m+n)/2);
v.b.y=v.a.y+sin((m+n)/2);
returnintersection(u,v);
}
3、垂心
point perpencenter(point a,point b,pointc){
lineu,v;
u.a=c;
u.b.x=u.a.x-a.y+b.y;
u.b.y=u.a.y+a.x-b.x;
v.a=b;
v.b.x=v.a.x-a.y+c.y;
v.b.y=v.a.y+a.x-c.x;
returnintersection(u,v);
}
4、重心
//到三角形三顶点距离的平方和最小的点
//三角形内到三边距离之积最大的点
point barycenter(point a,point b,point c){
lineu,v;
u.a.x=(a.x+b.x)/2;
u.a.y=(a.y+b.y)/2;
u.b=c;
v.a.x=(a.x+c.x)/2;
v.a.y=(a.y+c.y)/2;
v.b=b;
returnintersection(u,v);
}
5、费马点,到三角形三顶点距离之和最小的点
point fermentpoint(point a,point b,pointc){
pointu,v;
doublestep=fabs(a.x)+fabs(a.y)+fabs(b.x)+fabs(b.y)+fabs(c.x)+fabs(c.y);
inti,j,k;
u.x=(a.x+b.x+c.x)/3;
u.y=(a.y+b.y+c.y)/3;
while(step>1e-10)
for (k=0;k<10;step/=2,k++)
for(i=-1;i<=1;i++)
for (j=-1;j<=1;j++){
v.x=u.x+step*i;
v.y=u.y+step*j;
if(distance(u,a)+distance(u,b)+distance(u,c)>distance(v,a)+distance(v,b)+distance(v,c))
u=v;
}
returnu;
}
6、三维几何
//三维几何函数库
#include <math.h>
#define eps 1e-8
#define zero(x)(((x)>0?(x):-(x))<eps)
struct point3{double x,y,z;};
struct line3{point3 a,b;};
struct plane3{point3 a,b,c;};
1、计算cross product U x V
point3 xmult(point3 u,point3 v){
point3ret;
ret.x=u.y*v.z-v.y*u.z;
ret.y=u.z*v.x-u.x*v.z;
ret.z=u.x*v.y-u.y*v.x;
returnret;
}
2、计算dot product U . V
double dmult(point3 u,point3 v){
returnu.x*v.x+u.y*v.y+u.z*v.z;
}
3、矢量差 U - V
point3 subt(point3 u,point3 v){
point3ret;
ret.x=u.x-v.x;
ret.y=u.y-v.y;
ret.z=u.z-v.z;
returnret;
}
4、取平面法向量
point3 pvec(plane3 s){
returnxmult(subt(s.a,s.b),subt(s.b,s.c));
}
point3 pvec(point3 s1,point3 s2,point3 s3){
returnxmult(subt(s1,s2),subt(s2,s3));
}
5、两点距离,单参数取向量大小
double distance(point3 p1,point3 p2){
returnsqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y)+(p1.z-p2.z)*(p1.z-p2.z));
}
6、向量大小
double vlen(point3 p){
returnsqrt(p.x*p.x+p.y*p.y+p.z*p.z);
}
7、判三点共线
int dots_inline(point3 p1,point3 p2,point3p3){
returnvlen(xmult(subt(p1,p2),subt(p2,p3)))<eps;
}
8、判四点共面
int dots_onplane(point3 a,point3 b,point3c,point3 d){
returnzero(dmult(pvec(a,b,c),subt(d,a)));
}
9、判点是否在线段上,包括端点和共线
int dot_online_in(point3 p,line3 l){
returnzero(vlen(xmult(subt(p,l.a),subt(p,l.b))))&&(l.a.x-p.x)*(l.b.x-p.x)<eps&&
(l.a.y-p.y)*(l.b.y-p.y)<eps&&(l.a.z-p.z)*(l.b.z-p.z)<eps;
}
int dot_online_in(point3 p,point3 l1,point3l2){
returnzero(vlen(xmult(subt(p,l1),subt(p,l2))))&&(l1.x-p.x)*(l2.x-p.x)<eps&&
(l1.y-p.y)*(l2.y-p.y)<eps&&(l1.z-p.z)*(l2.z-p.z)<eps;
}
10、判点是否在线段上,不包括端点
int dot_online_ex(point3 p,line3 l){
returndot_online_in(p,l)&&(!zero(p.x-l.a.x)||!zero(p.y-l.a.y)||!zero(p.z-l.a.z))&&
(!zero(p.x-l.b.x)||!zero(p.y-l.b.y)||!zero(p.z-l.b.z));
}
int dot_online_ex(point3 p,point3 l1,point3l2){
returndot_online_in(p,l1,l2)&&(!zero(p.x-l1.x)||!zero(p.y-l1.y)||!zero(p.z-l1.z))&&
(!zero(p.x-l2.x)||!zero(p.y-l2.y)||!zero(p.z-l2.z));
}
11、判点是否在空间三角形上,包括边界,三点共线无意义
int dot_inplane_in(point3 p,plane3 s){
returnzero(vlen(xmult(subt(s.a,s.b),subt(s.a,s.c)))-vlen(xmult(subt(p,s.a),subt(p,s.b)))-
vlen(xmult(subt(p,s.b),subt(p,s.c)))-vlen(xmult(subt(p,s.c),subt(p,s.a))));
}
int dot_inplane_in(point3 p,point3s1,point3 s2,point3 s3){
returnzero(vlen(xmult(subt(s1,s2),subt(s1,s3)))-vlen(xmult(subt(p,s1),subt(p,s2)))-
vlen(xmult(subt(p,s2),subt(p,s3)))-vlen(xmult(subt(p,s3),subt(p,s1))));
}
12、判点是否在空间三角形上,不包括边界,三点共线无意义
int dot_inplane_ex(point3 p,plane3 s){
returndot_inplane_in(p,s)&&vlen(xmult(subt(p,s.a),subt(p,s.b)))>eps&&
vlen(xmult(subt(p,s.b),subt(p,s.c)))>eps&&vlen(xmult(subt(p,s.c),subt(p,s.a)))>eps;
}
int dot_inplane_ex(point3 p,point3s1,point3 s2,point3 s3){
returndot_inplane_in(p,s1,s2,s3)&&vlen(xmult(subt(p,s1),subt(p,s2)))>eps&&
vlen(xmult(subt(p,s2),subt(p,s3)))>eps&&vlen(xmult(subt(p,s3),subt(p,s1)))>eps;
}
13、判两点在线段同侧,点在线段上返回0,不共面无意义
int same_side(point3 p1,point3 p2,line3 l){
returndmult(xmult(subt(l.a,l.b),subt(p1,l.b)),xmult(subt(l.a,l.b),subt(p2,l.b)))>eps;
}
int same_side(point3 p1,point3 p2,point3l1,point3 l2){
returndmult(xmult(subt(l1,l2),subt(p1,l2)),xmult(subt(l1,l2),subt(p2,l2)))>eps;
}
14、判两点在线段异侧,点在线段上返回0,不共面无意义
int opposite_side(point3 p1,point3 p2,line3l){
returndmult(xmult(subt(l.a,l.b),subt(p1,l.b)),xmult(subt(l.a,l.b),subt(p2,l.b)))<-eps;
}
int opposite_side(point3 p1,point3p2,point3 l1,point3 l2){
returndmult(xmult(subt(l1,l2),subt(p1,l2)),xmult(subt(l1,l2),subt(p2,l2)))<-eps;
}
15、判两点在平面同侧,点在平面上返回0
int same_side(point3 p1,point3 p2,plane3s){
returndmult(pvec(s),subt(p1,s.a))*dmult(pvec(s),subt(p2,s.a))>eps;
}
int same_side(point3 p1,point3 p2,point3s1,point3 s2,point3 s3){
returndmult(pvec(s1,s2,s3),subt(p1,s1))*dmult(pvec(s1,s2,s3),subt(p2,s1))>eps;
}
16、判两点在平面异侧,点在平面上返回0
int opposite_side(point3 p1,point3p2,plane3 s){
returndmult(pvec(s),subt(p1,s.a))*dmult(pvec(s),subt(p2,s.a))<-eps;
}
int opposite_side(point3 p1,point3p2,point3 s1,point3 s2,point3 s3){
returndmult(pvec(s1,s2,s3),subt(p1,s1))*dmult(pvec(s1,s2,s3),subt(p2,s1))<-eps;
}
17、判两直线平行
int parallel(line3 u,line3 v){
returnvlen(xmult(subt(u.a,u.b),subt(v.a,v.b)))<eps;
}
int parallel(point3 u1,point3 u2,point3v1,point3 v2){
returnvlen(xmult(subt(u1,u2),subt(v1,v2)))<eps;
}
18、判两平面平行
int parallel(plane3 u,plane3 v){
returnvlen(xmult(pvec(u),pvec(v)))<eps;
}
int parallel(point3 u1,point3 u2,point3u3,point3 v1,point3 v2,point3 v3){
returnvlen(xmult(pvec(u1,u2,u3),pvec(v1,v2,v3)))<eps;
}
19、判直线与平面平行
int parallel(line3 l,plane3 s){
returnzero(dmult(subt(l.a,l.b),pvec(s)));
}
int parallel(point3 l1,point3 l2,point3s1,point3 s2,point3 s3){
returnzero(dmult(subt(l1,l2),pvec(s1,s2,s3)));
}
20、判两直线垂直
int perpendicular(line3 u,line3 v){
returnzero(dmult(subt(u.a,u.b),subt(v.a,v.b)));
}
int perpendicular(point3 u1,point3u2,point3 v1,point3 v2){
returnzero(dmult(subt(u1,u2),subt(v1,v2)));
}
21、判两平面垂直
int perpendicular(plane3 u,plane3 v){
returnzero(dmult(pvec(u),pvec(v)));
}
int perpendicular(point3 u1,point3u2,point3 u3,point3 v1,point3 v2,point3 v3){
returnzero(dmult(pvec(u1,u2,u3),pvec(v1,v2,v3)));
}
22、判直线与平面平行
int perpendicular(line3 l,plane3 s){
returnvlen(xmult(subt(l.a,l.b),pvec(s)))<eps;
}
int perpendicular(point3 l1,point3l2,point3 s1,point3 s2,point3 s3){
returnvlen(xmult(subt(l1,l2),pvec(s1,s2,s3)))<eps;
}
23、判两线段相交,包括端点和部分重合
int intersect_in(line3 u,line3 v){
if(!dots_onplane(u.a,u.b,v.a,v.b))
return 0;
if(!dots_inline(u.a,u.b,v.a)||!dots_inline(u.a,u.b,v.b))
return !same_side(u.a,u.b,v)&&!same_side(v.a,v.b,u);
returndot_online_in(u.a,v)||dot_online_in(u.b,v)||dot_online_in(v.a,u)||dot_online_in(v.b,u);
}
int intersect_in(point3 u1,point3 u2,point3v1,point3 v2){
if(!dots_onplane(u1,u2,v1,v2))
return 0;
if(!dots_inline(u1,u2,v1)||!dots_inline(u1,u2,v2))
return!same_side(u1,u2,v1,v2)&&!same_side(v1,v2,u1,u2);
returndot_online_in(u1,v1,v2)||dot_online_in(u2,v1,v2)||dot_online_in(v1,u1,u2)||dot_online_in(v2,u1,u2);
}
24、判两线段相交,不包括端点和部分重合
int intersect_ex(line3 u,line3 v){
returndots_onplane(u.a,u.b,v.a,v.b)&&opposite_side(u.a,u.b,v)&&opposite_side(v.a,v.b,u);
}
int intersect_ex(point3 u1,point3 u2,point3v1,point3 v2){
returndots_onplane(u1,u2,v1,v2)&&opposite_side(u1,u2,v1,v2)&&opposite_side(v1,v2,u1,u2);
}
25、判线段与空间三角形相交,包括交于边界和(部分)包含
int intersect_in(line3 l,plane3 s){
return!same_side(l.a,l.b,s)&&!same_side(s.a,s.b,l.a,l.b,s.c)&&
!same_side(s.b,s.c,l.a,l.b,s.a)&&!same_side(s.c,s.a,l.a,l.b,s.b);
}
int intersect_in(point3 l1,point3 l2,point3s1,point3 s2,point3 s3){
return!same_side(l1,l2,s1,s2,s3)&&!same_side(s1,s2,l1,l2,s3)&&
!same_side(s2,s3,l1,l2,s1)&&!same_side(s3,s1,l1,l2,s2);
}
26、判线段与空间三角形相交,不包括交于边界和(部分)包含
int intersect_ex(line3 l,plane3 s){
returnopposite_side(l.a,l.b,s)&&opposite_side(s.a,s.b,l.a,l.b,s.c)&&
opposite_side(s.b,s.c,l.a,l.b,s.a)&&opposite_side(s.c,s.a,l.a,l.b,s.b);
}
int intersect_ex(point3 l1,point3 l2,point3s1,point3 s2,point3 s3){
returnopposite_side(l1,l2,s1,s2,s3)&&opposite_side(s1,s2,l1,l2,s3)&&
opposite_side(s2,s3,l1,l2,s1)&&opposite_side(s3,s1,l1,l2,s2);
}
27、计算两直线交点,注意事先判断直线是否共面和平行!
//线段交点请另外判线段相交(同时还是要判断是否平行!)
point3 intersection(line3 u,line3 v){
point3ret=u.a;
doublet=((u.a.x-v.a.x)*(v.a.y-v.b.y)-(u.a.y-v.a.y)*(v.a.x-v.b.x))
/((u.a.x-u.b.x)*(v.a.y-v.b.y)-(u.a.y-u.b.y)*(v.a.x-v.b.x));
ret.x+=(u.b.x-u.a.x)*t;
ret.y+=(u.b.y-u.a.y)*t;
ret.z+=(u.b.z-u.a.z)*t;
returnret;
}
point3 intersection(point3 u1,point3u2,point3 v1,point3 v2){
point3ret=u1;
doublet=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))
/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
ret.x+=(u2.x-u1.x)*t;
ret.y+=(u2.y-u1.y)*t;
ret.z+=(u2.z-u1.z)*t;
returnret;
}
28、计算直线与平面交点,注意事先判断是否平行,并保证三点不共线!
//线段和空间三角形交点请另外判断
point3 intersection(line3 l,plane3 s){
point3ret=pvec(s);
doublet=(ret.x*(s.a.x-l.a.x)+ret.y*(s.a.y-l.a.y)+ret.z*(s.a.z-l.a.z))/
(ret.x*(l.b.x-l.a.x)+ret.y*(l.b.y-l.a.y)+ret.z*(l.b.z-l.a.z));
ret.x=l.a.x+(l.b.x-l.a.x)*t;
ret.y=l.a.y+(l.b.y-l.a.y)*t;
ret.z=l.a.z+(l.b.z-l.a.z)*t;
returnret;
}
point3 intersection(point3 l1,point3l2,point3 s1,point3 s2,point3 s3){
point3ret=pvec(s1,s2,s3);
doublet=(ret.x*(s1.x-l1.x)+ret.y*(s1.y-l1.y)+ret.z*(s1.z-l1.z))/
(ret.x*(l2.x-l1.x)+ret.y*(l2.y-l1.y)+ret.z*(l2.z-l1.z));
ret.x=l1.x+(l2.x-l1.x)*t;
ret.y=l1.y+(l2.y-l1.y)*t;
ret.z=l1.z+(l2.z-l1.z)*t;
returnret;
}
29、计算两平面交线,注意事先判断是否平行,并保证三点不共线!
line3 intersection(plane3 u,plane3 v){
line3ret;
ret.a=parallel(v.a,v.b,u.a,u.b,u.c)?intersection(v.b,v.c,u.a,u.b,u.c):intersection(v.a,v.b,u.a,u.b,u.c);
ret.b=parallel(v.c,v.a,u.a,u.b,u.c)?intersection(v.b,v.c,u.a,u.b,u.c):intersection(v.c,v.a,u.a,u.b,u.c);
returnret;
}
line3 intersection(point3 u1,point3u2,point3 u3,point3 v1,point3 v2,point3 v3){
line3ret;
ret.a=parallel(v1,v2,u1,u2,u3)?intersection(v2,v3,u1,u2,u3):intersection(v1,v2,u1,u2,u3);
ret.b=parallel(v3,v1,u1,u2,u3)?intersection(v2,v3,u1,u2,u3):intersection(v3,v1,u1,u2,u3);
returnret;
}
30、点到直线距离
double ptoline(point3 p,line3 l){
returnvlen(xmult(subt(p,l.a),subt(l.b,l.a)))/distance(l.a,l.b);
}
double ptoline(point3 p,point3 l1,point3l2){
returnvlen(xmult(subt(p,l1),subt(l2,l1)))/distance(l1,l2);
}
31、点到平面距离
double ptoplane(point3 p,plane3 s){
returnfabs(dmult(pvec(s),subt(p,s.a)))/vlen(pvec(s));
}
double ptoplane(point3 p,point3 s1,point3s2,point3 s3){
returnfabs(dmult(pvec(s1,s2,s3),subt(p,s1)))/vlen(pvec(s1,s2,s3));
}
32、直线到直线距离
double linetoline(line3 u,line3 v){
point3n=xmult(subt(u.a,u.b),subt(v.a,v.b));
returnfabs(dmult(subt(u.a,v.a),n))/vlen(n);
}
double linetoline(point3 u1,point3u2,point3 v1,point3 v2){
point3n=xmult(subt(u1,u2),subt(v1,v2));
returnfabs(dmult(subt(u1,v1),n))/vlen(n);
}
33、两直线夹角cos值
double angle_cos(line3 u,line3 v){
returndmult(subt(u.a,u.b),subt(v.a,v.b))/vlen(subt(u.a,u.b))/vlen(subt(v.a,v.b));
}
double angle_cos(point3 u1,point3 u2,point3v1,point3 v2){
returndmult(subt(u1,u2),subt(v1,v2))/vlen(subt(u1,u2))/vlen(subt(v1,v2));
}
34、两平面夹角cos值
double angle_cos(plane3 u,plane3 v){
returndmult(pvec(u),pvec(v))/vlen(pvec(u))/vlen(pvec(v));
}
double angle_cos(point3 u1,point3 u2,point3u3,point3 v1,point3 v2,point3 v3){
returndmult(pvec(u1,u2,u3),pvec(v1,v2,v3))/vlen(pvec(u1,u2,u3))/vlen(pvec(v1,v2,v3));
}
35、直线平面夹角sin值
double angle_sin(line3 l,plane3 s){
returndmult(subt(l.a,l.b),pvec(s))/vlen(subt(l.a,l.b))/vlen(pvec(s));
}
double angle_sin(point3 l1,point3 l2,point3s1,point3 s2,point3 s3){
returndmult(subt(l1,l2),pvec(s1,s2,s3))/vlen(subt(l1,l2))/vlen(pvec(s1,s2,s3));
}
7、网格
#define abs(x) ((x)>0?(x):-(x))
struct point{int x,y;};
int gcd(int a,int b){
returnb?gcd(b,a%b):a;
}
1、多边形上的网格点个数
int grid_onedge(int n,point* p){
inti,ret=0;
for(i=0;i<n;i++)
ret+=gcd(abs(p[i].x-p[(i+1)%n].x),abs(p[i].y-p[(i+1)%n].y));
returnret;
}
2、多边形内的网格点个数
int grid_inside(int n,point* p){
inti,ret=0;
for(i=0;i<n;i++)
ret+=p[(i+1)%n].y*(p[i].x-p[(i+2)%n].x);
return(abs(ret)-grid_onedge(n,p))/2+1;
}
8、圆
#include <math.h>
#define eps 1e-8
struct point{double x,y;};
double xmult(point p1,point p2,point p0){
return(p1.x-p0.x)*(p2.y-p0.y)-(p2.x-p0.x)*(p1.y-p0.y);
}
double distance(point p1,point p2){
returnsqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));
}
double disptoline(point p,point l1,pointl2){
returnfabs(xmult(p,l1,l2))/distance(l1,l2);
}
point intersection(point u1,point u2,pointv1,point v2){
pointret=u1;
doublet=((u1.x-v1.x)*(v1.y-v2.y)-(u1.y-v1.y)*(v1.x-v2.x))
/((u1.x-u2.x)*(v1.y-v2.y)-(u1.y-u2.y)*(v1.x-v2.x));
ret.x+=(u2.x-u1.x)*t;
ret.y+=(u2.y-u1.y)*t;
returnret;
}
1、判直线和圆相交,包括相切
int intersect_line_circle(point c,doubler,point l1,point l2){
returndisptoline(c,l1,l2)<r+eps;
}
2、判线段和圆相交,包括端点和相切
int intersect_seg_circle(point c,doubler,point l1,point l2){
doublet1=distance(c,l1)-r,t2=distance(c,l2)-r;
pointt=c;
if(t1<eps||t2<eps)
return t1>-eps||t2>-eps;
t.x+=l1.y-l2.y;
t.y+=l2.x-l1.x;
returnxmult(l1,c,t)*xmult(l2,c,t)<eps&&disptoline(c,l1,l2)-r<eps;
}
3、判圆和圆相交,包括相切
int intersect_circle_circle(point c1,doubler1,point c2,double r2){
returndistance(c1,c2)<r1+r2+eps&&distance(c1,c2)>fabs(r1-r2)-eps;
}
4、计算圆上到点p最近点,如p与圆心重合,返回p本身
point dot_to_circle(point c,double r,pointp){
pointu,v;
if(distance(p,c)<eps)
return p;
u.x=c.x+r*fabs(c.x-p.x)/distance(c,p);
u.y=c.y+r*fabs(c.y-p.y)/distance(c,p)*((c.x-p.x)*(c.y-p.y)<0?-1:1);
v.x=c.x-r*fabs(c.x-p.x)/distance(c,p);
v.y=c.y-r*fabs(c.y-p.y)/distance(c,p)*((c.x-p.x)*(c.y-p.y)<0?-1:1);
returndistance(u,p)<distance(v,p)?u:v;
}
5、计算直线与圆的交点,保证直线与圆有交点
//计算线段与圆的交点可用这个函数后判点是否在线段上
void intersection_line_circle(pointc,double r,point l1,point l2,point& p1,point& p2){
pointp=c;
doublet;
p.x+=l1.y-l2.y;
p.y+=l2.x-l1.x;
p=intersection(p,c,l1,l2);
t=sqrt(r*r-distance(p,c)*distance(p,c))/distance(l1,l2);
p1.x=p.x+(l2.x-l1.x)*t;
p1.y=p.y+(l2.y-l1.y)*t;
p2.x=p.x-(l2.x-l1.x)*t;
p2.y=p.y-(l2.y-l1.y)*t;
}
6、计算圆与圆的交点,保证圆与圆有交点,圆心不重合
void intersection_circle_circle(pointc1,double r1,point c2,double r2,point& p1,point& p2){
pointu,v;
doublet;
t=(1+(r1*r1-r2*r2)/distance(c1,c2)/distance(c1,c2))/2;
u.x=c1.x+(c2.x-c1.x)*t;
u.y=c1.y+(c2.y-c1.y)*t;
v.x=u.x+c1.y-c2.y;
v.y=u.y-c1.x+c2.x;
intersection_line_circle(c1,r1,u,v,p1,p2);
}
十四、数论
1、阶乘最后非0位
//求阶乘最后非零位,复杂度O(nlogn)
//返回该位,n以字符串方式传入
#include <string.h>
#define MAXN 10000
int lastdigit(char* buf){
constint mod[20]={1,1,2,6,4,2,2,4,2,8,4,4,8,4,6,8,8,6,8,2};
intlen=strlen(buf),a[MAXN],i,c,ret=1;
if(len==1)
return mod[buf[0]-'0'];
for(i=0;i<len;i++)
a[i]=buf[len-1-i]-'0';
for(;len;len-=!a[len-1]){
ret=ret*mod[a[1]%2*10+a[0]]%5;
for (c=0,i=len-1;i>=0;i--)
c=c*10+a[i],a[i]=c/5,c%=5;
}
returnret+ret%2*5;
}
2、模线性方程组
#ifdef WIN32
typedef __int64 i64;
#else
typedef long long i64;
#endif
//扩展Euclid求解gcd(a,b)=ax+by
int ext_gcd(int a,int b,int& x,int&y){
intt,ret;
if(!b){
x=1,y=0;
return a;
}
ret=ext_gcd(b,a%b,x,y);
t=x,x=y,y=t-a/b*y;
returnret;
}
//计算m^a, O(loga), 本身没什么用, 注意这个按位处理的方法:-P
int exponent(int m,int a){
intret=1;
for(;a;a>>=1,m*=m)
if (a&1)
ret*=m;
returnret;
}
//计算幂取模a^b mod n, O(logb)
int modular_exponent(int a,int b,int n){//a^b mod n
intret=1;
for(;b;b>>=1,a=(int)((i64)a)*a%n)
if (b&1)
ret=(int)((i64)ret)*a%n;
returnret;
}
//求解模线性方程ax=b (mod n)
//返回解的个数,解保存在sol[]中
//要求n>0,解的范围0..n-1
int modular_linear(int a,int b,int n,int*sol){
intd,e,x,y,i;
d=ext_gcd(a,n,x,y);
if(b%d)
return 0;
e=(x*(b/d)%n+n)%n;
for(i=0;i<d;i++)
sol[i]=(e+i*(n/d))%n;
returnd;
}
//求解模线性方程组(中国余数定理)
// x= b[0] (mod w[0])
// x= b[1] (mod w[1])
// ...
// x= b[k-1] (mod w[k-1])
//要求w[i]>0,w[i]与w[j]互质,解的范围1..n,n=w[0]*w[1]*...*w[k-1]
int modular_linear_system(int b[],intw[],int k){
intd,x,y,a=0,m,n=1,i;
for(i=0;i<k;i++)
n*=w[i];
for(i=0;i<k;i++){
m=n/w[i];
d=ext_gcd(w[i],m,x,y);
a=(a+y*m*b[i])%n;
}
return(a+n)%n;
}
3、素数
//用素数表判定素数,先调用initprime
int plist[10000],pcount=0;
int prime(int n){
inti;
if((n!=2&&!(n%2))||(n!=3&&!(n%3))||(n!=5&&!(n%5))||(n!=7&&!(n%7)))
return 0;
for(i=0;plist[i]*plist[i]<=n;i++)
if (!(n%plist[i]))
return0;
returnn>1;
}
void initprime(){
inti;
for(plist[pcount++]=2,i=3;i<50000;i++)
if (prime(i))
plist[pcount++]=i;
}
//miller rabin
//判断自然数n是否为素数
//time越高失败概率越低,一般取10到50
#include <stdlib.h>
#ifdef WIN32
typedef __int64 i64;
#else
typedef long long i64;
#endif
int modular_exponent(int a,int b,int n){//a^b mod n
intret;
for(;b;b>>=1,a=(int)((i64)a)*a%n)
if (b&1)
ret=(int)((i64)ret)*a%n;
returnret;
}
// Carmicheal number:561,41041,825265,321197185
int miller_rabin(int n,int time=10){
if(n==1||(n!=2&&!(n%2))||(n!=3&&!(n%3))||(n!=5&&!(n%5))||(n!=7&&!(n%7)))
return 0;
while(time--)
if(modular_exponent(((rand()&0x7fff<<16)+rand()&0x7fff+rand()&0x7fff)%(n-1)+1,n-1,n)!=1)
return0;
return1;
}
4、欧拉函数
int gcd(int a,int b){
returnb?gcd(b,a%b):a;
}
inline int lcm(int a,int b){
returna/gcd(a,b)*b;
}
//求1..n-1中与n互质的数的个数
int eular(int n){
intret=1,i;
for(i=2;i*i<=n;i++)
if (n%i==0){
n/=i,ret*=i-1;
while(n%i==0)
n/=i,ret*=i;
}
if(n>1)
ret*=n-1;
returnret;
}
5、返回x的二进制表示中从低到高的第i位
语法:result=BitAt(int x, int i);
参数:
x:十进制 x
i:要求二进制的第i位
返回值:返回x的二进制表示中从低到高的第i位
注意:
最低位为第一位
源程序:
int BitAt(int x, int i)
{
return ( x & (1 << (i-1)));
}
6、质因数分解
语法:result=int reduce(int prime[],int pn,int n,intrest[])
参数:
Prime[]:素数表,至少需要达到sqrt(n)
pn:素数表的元素个数
N:待分解的数
Rest:分解结果,按照升序排列
返回值:分解因子个数
源程序:
int reduce(int prime[],int pn,int n,intrest[])
{
int i,k=0;
for(i=0;i<pn;i++)
{
if (n==1) break;
if (prime[i]*prime[i]>n){rest[k++]=n;break;}
while(n%prime[i]==0)
{
n/=prime[i];
rest[k++]=prime[i];
}
}
return k;
}
7、幂取模
举例:输出a^n mod m的值
int pow_mod(int a,int n,int m)
{
if(n==0)
return 1;
int x=pow_mod(a,n/2,m);
long long ans=(long long)x*x%m;
if(n%2==1)
ans=ans*a%m;
return (int)ans;
}
8、求N^N最左面的数
举例:
#include<iostream>
#include<cmath>
using namespace std;
int main()
{
__int64 cas,b,i,d;
double a,m,n,c;
cin>>cas;
for(i=0;i<cas;i++)
{
cin>>n;
a=n*log10(n);
b=(__int64)(a);
c=a-b;
d=(__int64)(pow(10,c));
cout<<d<<endl;
}
return 0;
}
9、求Fibonacci的前四位(其实前几位都行)
思路:
以下是大牛的解释:
先看对数的性质,loga(b^c)=c*loga(b),loga(b*c)=loga(b)+loga(c);
假设给出一个数10234432,那么log10(10234432)=log10(1.0234432*10^7)=log10(1.0234432)+7;
log10(1.0234432)就是log10(10234432)的小数部分.
log10(1.0234432)=0.010063744
10^0.010063744=1.023443198
那么要取几位就很明显了吧~
先取对数(对10取),然后得到结果的小数部分bit,pow(10.0,bit)以后如果答案还是<1000那么就一直乘10。
注意偶先处理了0~20项是为了方便处理~
这题要利用到数列的公式:an=(1/√5) *[((1+√5)/2)^n-((1-√5)/2)^n](n=1,2,3.....)
取完对数
log10(an)=-0.5*log10(5.0)+((double)n)*log(f)/log(10.0)+log10(1-((1-√5)/(1+√5))^n)
其中f=(sqrt(5.0)+1.0)/2.0;
因为log10(1-((1-√5)/(1+√5))^n)趋近于0
所以可以写成log10(an)=-0.5*log10(5.0)+((double)n)*log(f)/log(10.0);
最后取其小数部分。
代码:
#include<iostream>
#include<cmath>
#include<cstdio>
using namespace std;
const double s = (sqrt(5.0)+1.0)/2;
int main()
{
int n,i;
doublebit;
int fac[21] = { 0 , 1 };
for(i = 2; i < 21; i++)
fac[i] = fac[i-1] + fac [i-2];
while(cin >> n)
{
if(n <= 20) {
cout << fac[n] << endl;
continue;
}
else{
bit = -0.5*log(5.0)/log(10.0)+((double)n)*log(s)/log(10.0);//调用公式
bit = bit - floor(bit); //取小数部分└(^o^)┘
bit = pow(10.0,bit);
while(bit < 1000) //要求四位,所以要将小数点右边的数移到左边直到符合要求
bit = 10.0 * bit;
cout << (int)bit << endl;
}
}
return 0;
}
10、2^14以内的素数
{
2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31,37, 41, 43, 47, 53, 59, 61, 67, 71, \
73, 79, 83, 89, 97, 101, 103, 107, 109,113, 127, 131, 137, 139, 149, 151, \
157, 163, 167, 173, 179, 181, 191, 193,197, 199, 211, 223, 227, 229, 233, \
239, 241, 251, 257, 263, 269, 271, 277,281, 283, 293, 307, 311, 313, 317, \
331, 337, 347, 349, 353, 359, 367, 373,379, 383, 389, 397, 401, 409, 419, \
421, 431, 433, 439, 443, 449, 457, 461,463, 467, 479, 487, 491, 499, 503, \
509, 521, 523, 541, 547, 557, 563, 569,571, 577, 587, 593, 599, 601, 607, \
613, 617, 619, 631, 641, 643, 647, 653,659, 661, 673, 677, 683, 691, 701, \
709, 719, 727, 733, 739, 743, 751, 757,761, 769, 773, 787, 797, 809, 811, \
821, 823, 827, 829, 839, 853, 857, 859,863, 877, 881, 883, 887, 907, 911, \
919, 929, 937, 941, 947, 953, 967, 971,977, 983, 991, 997, 1009, 1013, 1019, \
1021, 1031, 1033, 1039, 1049, 1051, 1061,1063, 1069, 1087, 1091, 1093, 1097, \
1103, 1109, 1117, 1123, 1129, 1151, 1153,1163, 1171, 1181, 1187, 1193, 1201, \
1213, 1217, 1223, 1229, 1231, 1237, 1249,1259, 1277, 1279, 1283, 1289, 1291, \
1297, 1301, 1303, 1307, 1319, 1321, 1327,1361, 1367, 1373, 1381, 1399, 1409, \
1423, 1427, 1429, 1433, 1439, 1447, 1451,1453, 1459, 1471, 1481, 1483, 1487, \
1489, 1493, 1499, 1511, 1523, 1531, 1543,1549, 1553, 1559, 1567, 1571, 1579, \
1583, 1597, 1601, 1607, 1609, 1613, 1619,1621, 1627, 1637, 1657, 1663, 1667, \
1669, 1693, 1697, 1699, 1709, 1721, 1723,1733, 1741, 1747, 1753, 1759, 1777, \
1783, 1787, 1789, 1801, 1811, 1823, 1831,1847, 1861, 1867, 1871, 1873, 1877, \
1879, 1889, 1901, 1907, 1913, 1931, 1933,1949, 1951, 1973, 1979, 1987, 1993, \
1997, 1999, 2003, 2011, 2017, 2027, 2029,2039, 2053, 2063, 2069, 2081, 2083, \
2087, 2089, 2099, 2111, 2113, 2129, 2131,2137, 2141, 2143, 2153, 2161, 2179, \
2203, 2207, 2213, 2221, 2237, 2239, 2243,2251, 2267, 2269, 2273, 2281, 2287, \
2293, 2297, 2309, 2311, 2333, 2339, 2341,2347, 2351, 2357, 2371, 2377, 2381, \
2383, 2389, 2393, 2399, 2411, 2417, 2423,2437, 2441, 2447, 2459, 2467, 2473, \
2477, 2503, 2521, 2531, 2539, 2543, 2549,2551, 2557, 2579, 2591, 2593, 2609, \
2617, 2621, 2633, 2647, 2657, 2659, 2663,2671, 2677, 2683, 2687, 2689, 2693, \
2699, 2707, 2711, 2713, 2719, 2729, 2731,2741, 2749, 2753, 2767, 2777, 2789, \
2791, 2797, 2801, 2803, 2819, 2833, 2837,2843, 2851, 2857, 2861, 2879, 2887, \
2897, 2903, 2909, 2917, 2927, 2939, 2953,2957, 2963, 2969, 2971, 2999, 3001, \
3011, 3019, 3023, 3037, 3041, 3049, 3061,3067, 3079, 3083, 3089, 3109, 3119, \
3121, 3137, 3163, 3167, 3169, 3181, 3187,3191, 3203, 3209, 3217, 3221, 3229, \
3251, 3253, 3257, 3259, 3271, 3299, 3301,3307, 3313, 3319, 3323, 3329, 3331, \
3343, 3347, 3359, 3361, 3371, 3373, 3389,3391, 3407, 3413, 3433, 3449, 3457, \
3461, 3463, 3467, 3469, 3491, 3499, 3511,3517, 3527, 3529, 3533, 3539, 3541, \
3547, 3557, 3559, 3571, 3581, 3583, 3593,3607, 3613, 3617, 3623, 3631, 3637, \
3643, 3659, 3671, 3673, 3677, 3691, 3697,3701, 3709, 3719, 3727, 3733, 3739, \
3761, 3767, 3769, 3779, 3793, 3797, 3803,3821, 3823, 3833, 3847, 3851, 3853, \
3863, 3877, 3881, 3889, 3907, 3911, 3917,3919, 3923, 3929, 3931, 3943, 3947, \
3967, 3989, 4001, 4003, 4007, 4013, 4019,4021, 4027, 4049, 4051, 4057, 4073, \
4079, 4091, 4093, 4099, 4111, 4127, 4129,4133, 4139, 4153, 4157, 4159, 4177, \
4201, 4211, 4217, 4219, 4229, 4231, 4241,4243, 4253, 4259, 4261, 4271, 4273, \
4283, 4289, 4297, 4327, 4337, 4339, 4349,4357, 4363, 4373, 4391, 4397, 4409, \
4421, 4423, 4441, 4447, 4451, 4457, 4463,4481, 4483, 4493, 4507, 4513, 4517, \
4519, 4523, 4547, 4549, 4561, 4567, 4583,4591, 4597, 4603, 4621, 4637, 4639, \
4643, 4649, 4651, 4657, 4663, 4673, 4679,4691, 4703, 4721, 4723, 4729, 4733, \
4751, 4759, 4783, 4787, 4789, 4793, 4799,4801, 4813, 4817, 4831, 4861, 4871, \
4877, 4889, 4903, 4909, 4919, 4931, 4933,4937, 4943, 4951, 4957, 4967, 4969, \
4973, 4987, 4993, 4999, 5003, 5009, 5011,5021, 5023, 5039, 5051, 5059, 5077, \
5081, 5087, 5099, 5101, 5107, 5113, 5119,5147, 5153, 5167, 5171, 5179, 5189, \
5197, 5209, 5227, 5231, 5233, 5237, 5261,5273, 5279, 5281, 5297, 5303, 5309, \
5323, 5333, 5347, 5351, 5381, 5387, 5393,5399, 5407, 5413, 5417, 5419, 5431, \
5437, 5441, 5443, 5449, 5471, 5477, 5479,5483, 5501, 5503, 5507, 5519, 5521, \
5527, 5531, 5557, 5563, 5569, 5573, 5581,5591, 5623, 5639, 5641, 5647, 5651, \
5653, 5657, 5659, 5669, 5683, 5689, 5693,5701, 5711, 5717, 5737, 5741, 5743, \
5749, 5779, 5783, 5791, 5801, 5807, 5813,5821, 5827, 5839, 5843, 5849, 5851, \
5857, 5861, 5867, 5869, 5879, 5881, 5897,5903, 5923, 5927, 5939, 5953, 5981, \
5987, 6007, 6011, 6029, 6037, 6043, 6047,6053, 6067, 6073, 6079, 6089, 6091, \
6101, 6113, 6121, 6131, 6133, 6143, 6151,6163, 6173, 6197, 6199, 6203, 6211, \
6217, 6221, 6229, 6247, 6257, 6263, 6269,6271, 6277, 6287, 6299, 6301, 6311, \
6317, 6323, 6329, 6337, 6343, 6353, 6359,6361, 6367, 6373, 6379, 6389, 6397, \
6421, 6427, 6449, 6451, 6469, 6473, 6481,6491, 6521, 6529, 6547, 6551, 6553, \
6563, 6569, 6571, 6577, 6581, 6599, 6607,6619, 6637, 6653, 6659, 6661, 6673, \
6679, 6689, 6691, 6701, 6703, 6709, 6719,6733, 6737, 6761, 6763, 6779, 6781, \
6791, 6793, 6803, 6823, 6827, 6829, 6833,6841, 6857, 6863, 6869, 6871, 6883, \
6899, 6907, 6911, 6917, 6947, 6949, 6959,6961, 6967, 6971, 6977, 6983, 6991, \
6997, 7001, 7013, 7019, 7027, 7039, 7043,7057, 7069, 7079, 7103, 7109, 7121, \
7127, 7129, 7151, 7159, 7177, 7187, 7193,7207, 7211, 7213, 7219, 7229, 7237, \
7243, 7247, 7253, 7283, 7297, 7307, 7309,7321, 7331, 7333, 7349, 7351, 7369, \
7393, 7411, 7417, 7433, 7451, 7457, 7459,7477, 7481, 7487, 7489, 7499, 7507, \
7517, 7523, 7529, 7537, 7541, 7547, 7549,7559, 7561, 7573, 7577, 7583, 7589, \
7591, 7603, 7607, 7621, 7639, 7643, 7649,7669, 7673, 7681, 7687, 7691, 7699, \
7703, 7717, 7723, 7727, 7741, 7753, 7757,7759, 7789, 7793, 7817, 7823, 7829, \
7841, 7853, 7867, 7873, 7877, 7879, 7883,7901, 7907, 7919, 7927, 7933, 7937, \
7949, 7951, 7963, 7993, 8009, 8011, 8017,8039, 8053, 8059, 8069, 8081, 8087, \
8089, 8093, 8101, 8111, 8117, 8123, 8147,8161, 8167, 8171, 8179, 8191, 8209, \
8219, 8221, 8231, 8233, 8237, 8243, 8263,8269, 8273, 8287, 8291, 8293, 8297, \
8311, 8317, 8329, 8353, 8363, 8369, 8377,8387, 8389, 8419, 8423, 8429, 8431, \
8443, 8447, 8461, 8467, 8501, 8513, 8521,8527, 8537, 8539, 8543, 8563, 8573, \
8581, 8597, 8599, 8609, 8623, 8627, 8629,8641, 8647, 8663, 8669, 8677, 8681, \
8689, 8693, 8699, 8707, 8713, 8719, 8731,8737, 8741, 8747, 8753, 8761, 8779, \
8783, 8803, 8807, 8819, 8821, 8831, 8837,8839, 8849, 8861, 8863, 8867, 8887, \
8893, 8923, 8929, 8933, 8941, 8951, 8963,8969, 8971, 8999, 9001, 9007, 9011, \
9013, 9029, 9041, 9043, 9049, 9059, 9067,9091, 9103, 9109, 9127, 9133, 9137, \
9151, 9157, 9161, 9173, 9181, 9187, 9199,9203, 9209, 9221, 9227, 9239, 9241, \
9257, 9277, 9281, 9283, 9293, 9311, 9319,9323, 9337, 9341, 9343, 9349, 9371, \
9377, 9391, 9397, 9403, 9413, 9419, 9421,9431, 9433, 9437, 9439, 9461, 9463, \
9467, 9473, 9479, 9491, 9497, 9511, 9521,9533, 9539, 9547, 9551, 9587, 9601, \
9613, 9619, 9623, 9629, 9631, 9643, 9649,9661, 9677, 9679, 9689, 9697, 9719, \
9721, 9733, 9739, 9743, 9749, 9767, 9769,9781, 9787, 9791, 9803, 9811, 9817, \
9829, 9833, 9839, 9851, 9857, 9859, 9871,9883, 9887, 9901, 9907, 9923, 9929, \
9931, 9941, 9949, 9967, 9973, 10007,10009, 10037, 10039, 10061, 10067, \
10069, 10079, 10091, 10093, 10099, 10103,10111, 10133, 10139, 10141, 10151, \
10159, 10163, 10169, 10177, 10181, 10193,10211, 10223, 10243, 10247, 10253, \
10259, 10267, 10271, 10273, 10289, 10301,10303, 10313, 10321, 10331, 10333, \
10337, 10343, 10357, 10369, 10391, 10399,10427, 10429, 10433, 10453, 10457, \
10459, 10463, 10477, 10487, 10499, 10501,10513, 10529, 10531, 10559, 10567, \
10589, 10597, 10601, 10607, 10613, 10627,10631, 10639, 10651, 10657, 10663, \
10667, 10687, 10691, 10709, 10711, 10723,10729, 10733, 10739, 10753, 10771, \
10781, 10789, 10799, 10831, 10837, 10847,10853, 10859, 10861, 10867, 10883, \
10889, 10891, 10903, 10909, 10937, 10939,10949, 10957, 10973, 10979, 10987, \
10993, 11003, 11027, 11047, 11057, 11059,11069, 11071, 11083, 11087, 11093, \
11113, 11117, 11119, 11131, 11149, 11159,11161, 11171, 11173, 11177, 11197, \
11213, 11239, 11243, 11251, 11257, 11261,11273, 11279, 11287, 11299, 11311, \
11317, 11321, 11329, 11351, 11353, 11369,11383, 11393, 11399, 11411, 11423, \
11437, 11443, 11447, 11467, 11471, 11483,11489, 11491, 11497, 11503, 11519, \
11527, 11549, 11551, 11579, 11587, 11593,11597, 11617, 11621, 11633, 11657, \
11677, 11681, 11689, 11699, 11701, 11717,11719, 11731, 11743, 11777, 11779, \
11783, 11789, 11801, 11807, 11813, 11821,11827, 11831, 11833, 11839, 11863, \
11867, 11887, 11897, 11903, 11909, 11923,11927, 11933, 11939, 11941, 11953, \
11959, 11969, 11971, 11981, 11987, 12007,12011, 12037, 12041, 12043, 12049, \
12071, 12073, 12097, 12101, 12107, 12109,12113, 12119, 12143, 12149, 12157, \
12161, 12163, 12197, 12203, 12211, 12227,12239, 12241, 12251, 12253, 12263, \
12269, 12277, 12281, 12289, 12301, 12323,12329, 12343, 12347, 12373, 12377, \
12379, 12391, 12401, 12409, 12413, 12421,12433, 12437, 12451, 12457, 12473, \
12479, 12487, 12491, 12497, 12503, 12511,12517, 12527, 12539, 12541, 12547, \
12553, 12569, 12577, 12583, 12589, 12601,12611, 12613, 12619, 12637, 12641, \
12647, 12653, 12659, 12671, 12689, 12697,12703, 12713, 12721, 12739, 12743, \
12757, 12763, 12781, 12791, 12799, 12809,12821, 12823, 12829, 12841, 12853, \
12889, 12893, 12899, 12907, 12911, 12917,12919, 12923, 12941, 12953, 12959, \
12967, 12973, 12979, 12983, 13001, 13003,13007, 13009, 13033, 13037, 13043, \
13049, 13063, 13093, 13099, 13103, 13109,13121, 13127, 13147, 13151, 13159, \
13163, 13171, 13177, 13183, 13187, 13217,13219, 13229, 13241, 13249, 13259, \
13267, 13291, 13297, 13309, 13313, 13327,13331, 13337, 13339, 13367, 13381, \
13397, 13399, 13411, 13417, 13421, 13441,13451, 13457, 13463, 13469, 13477, \
13487, 13499, 13513, 13523, 13537, 13553,13567, 13577, 13591, 13597, 13613, \
13619, 13627, 13633, 13649, 13669, 13679,13681, 13687, 13691, 13693, 13697, \
13709, 13711, 13721, 13723, 13729, 13751,13757, 13759, 13763, 13781, 13789, \
13799, 13807, 13829, 13831, 13841, 13859,13873, 13877, 13879, 13883, 13901, \
13903, 13907, 13913, 13921, 13931, 13933,13963, 13967, 13997, 13999, 14009, \
14011, 14029, 14033, 14051, 14057, 14071,14081, 14083, 14087, 14107, 14143, \
14149, 14153, 14159, 14173, 14177, 14197,14207, 14221, 14243, 14249, 14251, \
14281, 14293, 14303, 14321, 14323, 14327,14341, 14347, 14369, 14387, 14389, \
14401, 14407, 14411, 14419, 14423, 14431,14437, 14447, 14449, 14461, 14479, \
14489, 14503, 14519, 14533, 14537, 14543,14549, 14551, 14557, 14561, 14563, \
14591, 14593, 14621, 14627, 14629, 14633,14639, 14653, 14657, 14669, 14683, \
14699, 14713, 14717, 14723, 14731, 14737,14741, 14747, 14753, 14759, 14767, \
14771, 14779, 14783, 14797, 14813, 14821,14827, 14831, 14843, 14851, 14867, \
14869, 14879, 14887, 14891, 14897, 14923,14929, 14939, 14947, 14951, 14957, \
14969, 14983, 15013, 15017, 15031, 15053,15061, 15073, 15077, 15083, 15091, \
15101, 15107, 15121, 15131, 15137, 15139,15149, 15161, 15173, 15187, 15193, \
15199, 15217, 15227, 15233, 15241, 15259,15263, 15269, 15271, 15277, 15287, \
15289, 15299, 15307, 15313, 15319, 15329,15331, 15349, 15359, 15361, 15373, \
15377, 15383, 15391, 15401, 15413, 15427,15439, 15443, 15451, 15461, 15467, \
15473, 15493, 15497, 15511, 15527, 15541,15551, 15559, 15569, 15581, 15583, \
15601, 15607, 15619, 15629, 15641, 15643,15647, 15649, 15661, 15667, 15671, \
15679, 15683, 15727, 15731, 15733, 15737,15739, 15749, 15761, 15767, 15773, \
15787, 15791, 15797, 15803, 15809, 15817,15823, 15859, 15877, 15881, 15887, \
15889, 15901, 15907, 15913, 15919, 15923,15937, 15959, 15971, 15973, 15991, \
16001, 16007, 16033, 16057, 16061, 16063,16067, 16069, 16073, 16087, 16091, \
16097, 16103, 16111, 16127, 16139, 16141,16183, 16187, 16189, 16193, 16217, \
16223, 16229, 16231, 16249, 16253, 16267,16273, 16301, 16319, 16333, 16339, \
16349, 16361, 16363, 16369, 16381
}
11、求最大公约数,最小公倍数
最大公约数举例:
#include<iostream>
using namespace std;
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
cout<<gcd(24,36)<<endl;
return 0;
}
输出结果:
12
最小公倍数举例lcm:
#include<iostream>
using namespace std;
int gcd(int a,int b)
{
return b==0?a:gcd(b,a%b);
}
int lcm(int a,int b)
{
return a/gcd(a,b)*b;
}
int main()
{
cout<<24/gcd(24,36)*36<<endl;
return 0;
}
输出结果:
72
结论:最小公倍数lcm(a,b)=a/gcd(a,b)*b
12、用N个三角形最多可以把平面分成几个区域?
公式:f(n)=3*n*(n-1)+2
此题重在理解推导公式,f(n)=f(n-1)+6*(n-1),化简为:f(n)=3*n*(n-1)+2。 一个三角形的时候,再加一个三角形,每一条变会与第一个三角形的两条边相交,这样增加2个小三角形,即两个面。f(2)=3*2+f(1),再加一个三角形,每一条边会与前两个三角形的四条边相交,形成四个小三角形,f(3)=3*4+f(2),依次类推,即f(n)=3*2*(n-1)+f(n-1)。
13、循环小数换成分数
小数化分数分成两类。 一类:纯循环小数化分数,循环节做分子;连写几个九作分母,循环节有几位写几个九。例:0.3(3循环)=3/9(循环节的位数有一个,所以写一个9) 0.347(347循环)=347/999(3位循环节写3个9) 另一类:混循环小数化分数,小数部分减去不循环的数字作分子;连写几个9再紧接着连写几个0作分母,循环节是几个数就写几个9,不循环(小数部分)的数是几个就写几个0。例0.2134(34循环)=(2134-21)/9900 。
十五、日期
//日期函数
intdays[12]={31,28,31,30,31,30,31,31,30,31,30,31};
struct date{
intyear,month,day;
};
1、判闰年
inline int leap(int year){
return(year%4==0&&year%100!=0)||year%400==0;
}
2、判合法性
inline int legal(date a){
if(a.month<0||a.month>12)
return 0;
if(a.month==2)
returna.day>0&&a.day<=28+leap(a.year);
returna.day>0&&a.day<=days[a.month-1];
}
3、比较日期大小
inline int datecmp(date a,date b){
if(a.year!=b.year)
return a.year-b.year;
if(a.month!=b.month)
return a.month-b.month;
return a.day-b.day;
}
4、返回指定日期是星期几
int weekday(date a){
inttm=a.month>=3?(a.month-2):(a.month+10);
intty=a.month>=3?a.year:(a.year-1);
return(ty+ty/4-ty/100+ty/400+(int)(2.6*tm-0.2)+a.day)%7;
}
5、日期转天数偏移
int date2int(date a){
intret=a.year*365+(a.year-1)/4-(a.year-1)/100+(a.year-1)/400,i;
days[1]+=leap(a.year);
for(i=0;i<a.month-1;ret+=days[i++]);
days[1]=28;
returnret+a.day;
}
6、天数偏移转日期
date int2date(int a){
dateret;
ret.year=a/146097*400;
for(a%=146097;a>=365+leap(ret.year);a-=365+leap(ret.year),ret.year++);
days[1]+=leap(ret.year);
for(ret.month=1;a>=days[ret.month-1];a-=days[ret.month-1],ret.month++);
days[1]=28;
ret.day=a+1;
returnret;
}
- ACM资料整理
- ACM资料
- ACM资料
- ACM 资料
- 整理资料
- 资料整理
- 资料整理
- 资料整理
- 资料整理
- 资料整理
- 资料整理
- 资料整理
- 资料整理
- 资料整理
- 资料整理
- 资料整理
- 资料整理
- 资料整理
- JS高级程序设计(第2版)读书笔记第1-3章
- 在一个程序打开另一个程序
- SpringMvc + jQuery + json(JSON接受和发送)
- JS高级程序设计(第2版)读书笔记第4-5章
- 写一个函数,将其中的 \t 都转换成4个空格
- ACM资料整理
- 第11周项目1存储班长信息的学生类
- 一起talk Vim吧(第十八回:Vim插件之cscope续)
- 第八周项目1-复数类中的运算符重载
- Android小项目01--网络图片查看器
- android中ListView注意事项
- JS高级程序设计(第2版)读书笔记第6-7章
- android :EditText-> inputType参数类型说明
- Android小项目02--HTML查看器