Tips

1)字符串转换数字

1 if(str[i]>='0'&&str[i]<='9') {
2     int j=0; 
3     do{ 
4         j*=10;j+=int(str[i]-'0'); 
5         i++; 
6     }while(str[i]>='0'&&str[i]<='9');

 //实际上为读入优化的一部分

 

2)进制转换万能模板

 1 #include <cstdio>
 2 using namespace std;
 3 int x, s, k, i = 0;
 4 char ans[256];
 5 char trans(int x){
 6     return (x < 10) ? (x + '0') : (x - 10 + 'A');
 7 }
 8 int main(){
 9     scanf("%d%d", &x,&k);
10     if(x==0) printf("0");
11     else{
12         while (x){
13                int mod = x % k;
14             mod = (mod < 0) ? (mod - k) : mod;
15             ans[i++] = trans(mod);
16             x = (x - mod) / k;
17         }
18         while (i--) printf("%c", ans[i]);
19     }
20     return 0;
21 }

 附几个样例:

 

 

 

3)二维数组前缀和

注意前缀和的求法和面积的表示方法,对于二维数组的前缀和,先像一维数组那样求一遍每行的前缀和,再将每一个前缀和加上自己上面的点的前缀和。

而面积的表示:对于i,j点边长为l的正方形,前缀和表示:sum[i][j]-sum[i-l][j]-sum[i][j-l]+sum[i-l][j-l]

栗子:http://www.cnblogs.com/radiumlrb/p/5808285.html

http://www.cnblogs.com/radiumlrb/p/5808527.html

 

 

4)关于C标准下字符串输入的问题//2018-09-25

 

scanf接收字符时的格式是scanf("%c",&ch)(ch是定义过的接收键盘输入字符的变量,下同);。这种格式下,无论输入缓冲区里有多少字符,scanf("%c",&ch);都只接收最前面的一个赋给ch,但系统要以'\n'作为输入结束的命令,那么scanf("%c",&ch);在接收一个输入字符时必然会把'\n'遗留在缓冲区里。

这样问题就来了,由于'\n'也是一个字符,所以下一个scanf("%c",&ch2);就会把上一个scanf("%c",&ch);遗留在缓冲区里的'\n'接收并赋给ch2,这就造成第二个scanf("%c",&ch2);失去了从键盘接收用户输入的字符的机会(scanf("%c",&ch2)只接收一个字符),从而造成代码运行出错。

解决办法很多,在scanf("%c",&ch);语句前加getchar();,加fflush(stdin);,甚至把scanf("%c",&ch);写两遍都能凑效。但这不仅要消费空间时间,而且阅读也不直观。其实知道了原理解决起来就方便了,最简单的办法是把每一个类似scanf("%c",&ch);这样读字符的语句改写成scanf(" %c",&ch)(%前有个空格);就可以了,原理是这个空格会命令scanf跳过所有的广义空格(' '、'\t'、'\n'等)再接收字符——当然没有空格就不会有跳过动作——问题就迎刃而解了。

下面提供验证代码:

//#include "stdafx.h"//If the vc++6.0, with this line.
#include "stdio.h"
int main(void){
    char a,b;
    scanf(" %c",&a);
    scanf(" %c",&b);
    printf("%c %c\n",a,b);
    return 0;
}

  

 

5)循环中不要放置strlen等函数

 惨痛的教训

     strlen所作的仅仅是一个计数器的工作,它从内存的某个位置(可以是字符串开头,中间某个位置,甚至是某个不确定的内存区域)开始扫描,直到碰到第一个字符串结束符'\0'为止,然后返回计数器值(长度不包含'\0')。

我们用cin>>s和scanf(%s)输入字符串时,会在接受完字符串后在末尾加个'\0',也就是NULL作为字符串结束符。

所以用strlen函数求解字符串长度的时候,复杂度就是O(n)。如果在循环中用

for (int i = 0; i < strlen(s); ++i)//复杂度O(n2)
那就麻烦了,可能会超时,解决办法:

(1)先把strlen(s)用变量存储起来,再放入循环中;

(2)或者用s[i] != '\0';

(3)或者用string s存储,用s.size();

做poj1152的时候发现用i < s.size()和i < strlen(s)最终用时差不多。但是最好还是用前两种。

2.类似的还有sqrt函数
循环的时候要么先算出sqrt(x),要么就用i*i < x,最好不要用i < sqrt(x),增加复杂度。

其他的类似。

 

6)数组开大点不花钱,开小了会抓狂

3kw个int自己把握好

极限空间的题目:http://www.cnblogs.com/radiumlrb/p/5836629.html

 7)素数筛法

普通的线性筛法:

#include"cstdio"
#include"cstring"
using namespace std;
#define MAX 100000//求MAX范围内的素数
long long su[MAX],cnt;
bool isprime[MAX];
void prime()
{
    cnt=1;
    memset(isprime,1,sizeof(isprime));//初始化认为所有数都为素数
    isprime[0]=isprime[1]=0;//0和1不是素数
    for(long long i=2;i<=MAX;i++)
    {
        if(isprime[i])//保存素数
        {
            su[cnt++]=i;
        }
        for(long long j=i*2;j<=MAX;j+=i)//素数的倍数都为合数
        {
            isprime[j]=0;
        }
    }
}
int main()
{
    prime();
    for(long long i=1;i<cnt;i++)
        printf("%d  ",su[i]);
    return 0;
}

优化后的线性筛法:

#include"cstdio"
#include"cstring"
using namespace std;
#define MAX 100000//求MAX范围内的素数
long long su[MAX],cnt;
bool isprime[MAX];
void prime()
{
    cnt=1;
    memset(isprime,1,sizeof(isprime));//初始化认为所有数都为素数
    isprime[0]=isprime[1]=0;//0和1不是素数
    for(long long i=2;i<=MAX;i++)
    {
        if(isprime[i])
            su[cnt++]=i;//保存素数i
        for(long long j=1;j<cnt&&su[j]*i<MAX;j++)
        {
            isprime[su[j]*i]=0;//筛掉小于等于i的素数和i的积构成的合数
        }
    }
}
int main()
{
    prime();
    for(long long i=1;i<cnt;i++)
        printf("%d  ",su[i]);
    return 0;
}

普通的线性筛法虽然大大缩短了求素数的时间,但是实际上还是做了许多重复运算,比如2*3=6,在素数2的时候筛选了一遍,在素数为3时又筛选了一遍。如果只筛选小于等于素数i的素数与i的乘积,既不会造成重复筛选,又不会遗漏。时间复杂度几乎是线性的。

 

 

 

转载于:https://www.cnblogs.com/radiumlrb/p/5759524.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值