ACM资料整理

一、做题时应注意的地方

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,求不同划分的方案数fn)。

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开始的地址空间

注意:

  • 8
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值