各种测试
i++与++i
要尽量用++i
,因为i++
系统会开辟空间把之前的i
存下来。
#include<ctime>
#include<cstdio>
#define MAXN 100000000
#define MOD 1000000007
int Fib[MAXN+5];
int main(){
double t1,t2;
Fib[1]=Fib[2]=1;
t1=clock();
for(int i=3;i<=MAXN;i++)
Fib[i]=Fib[i-1]+Fib[i-2];
t2=clock();
printf("Time of 'i++': %.4lf s\n",(t2-t1)/1000);
for(int i=3;i<=MAXN;++i)
Fib[i]=Fib[i-1]+Fib[i-2];
t1=clock();
printf("Time of '++i': %.4lf s\n",(t1-t2)/1000);
}
结果:
Time of ‘i++’: 0.5880 s
Time of ‘++i’: 0.3370 s
发现MOD
没有用到,于是:
#include<ctime>
#include<cstdio>
#define MAXN 100000000
#define MOD 1000000007
int Fib[MAXN+5];
int main(){
double t1,t2;
Fib[1]=Fib[2]=1;
t1=clock();
for(int i=3;i<=MAXN;i++)
Fib[i]=(Fib[i-1]+Fib[i-2])%MOD;
t2=clock();
printf("Time of 'i++': %.4lf s\n",(t2-t1)/1000);
for(int i=3;i<=MAXN;++i)
Fib[i]=(Fib[i-1]+Fib[i-2])%MOD;
t1=clock();
printf("Time of '++i': %.4lf s\n",(t1-t2)/1000);
}
结果:
Time of ‘i++’: 1.2070 s
Time of ‘++i’: 1.0520 s
END
读入优化和输出优化
这个不多说,大概千万个数据能快
200
m
s
200ms
200ms,我喜欢用读入优化最主要的是可以这样写:x=read()+k
,如果用scanf
会多出一行。详情看这个博客:读入优化&输出优化。好像用fread
可以更快,我没有试过,可以看这篇博客(也是转载的):更快的读入优化fread。
神奇关键字
inline
把函数置为内联,增快调用速度。只适用于简单函数,如果复杂了,系统会自动忽略掉这些(例如AddEdge
之类的可以,有递归是肯定不行的,循环似乎也不行)。
如果inline
的函数里面有复杂的运算,但是是
O
(
1
)
O(1)
O(1)级别的,那是最好的。
#include<ctime>
#include<cstdio>
#define MAXN 100000000
void Cal(int &x){
x=x*(MAXN-1)%MAXN;
}
inline void inlineCal(int &x){
x=x*(MAXN-1)%MAXN;
}
int main(){
double t1,t2;
int x=0;
t1=clock();
for(int i=1;i<=MAXN;i++)
Cal(x);
t2=clock();
printf("Time of the function without 'inline': %.4lf S\n",(t2-t1)/1000);
for(int i=1;i<=MAXN;i++)
inlineCal(x);
t1=clock();
printf("Time of the function with 'inline': %.4lf S\n",(t1-t2)/1000);
}
结果:
Time of the function without ‘inline’: 1.4350 S
Time of the function with ‘inline’: 1.4170 S
话说做一亿次乘法和模运算会超过一秒……
register
变量前加上这个可以把它放在CPU寄存器里,但是太多了就不行了。
在一亿的数据下也就快了
100
m
s
100ms
100ms左右。
#include<ctime>
#include<cstdio>
#define MAXN 100000000
int main(){
double t1,t2;
register int x=1;
t1=clock();
for(int i=1;i<=MAXN;i++)
x=(x*2)%MAXN;
t2=clock();
printf("Time of the variables with 'register': %.4lf S\n",(t2-t1)/1000);
int a=1;
for(int i=1;i<=MAXN;i++)
a=(a*2)%MAXN;
t1=clock();
printf("Time of the variables without 'register': %.4lf S\n",(t1-t2)/1000);
}
结果:
Time of the variables with ‘register’: 0.8290 S
Time of the variables without ‘register’: 0.9400 S
各种类型的运算速度
从测试看来,char
、int
和bool
差别不大,char
最快(然而可以看看例题一的玄学超时),long long
瞬间变慢一半,所以对于某些一言不合就Ctrl+F全部换long long
的人来说超时也很正常,double
就不说了。
#include<ctime>
#include<cstdio>
#define MAXN 10000000
//开100000000运行不了,所以少了一个0
#define MOD 1000000007
int Fib1[MAXN+5];
bool Fib2[MAXN+5];
long long Fib3[MAXN+5];
char Fib4[MAXN+5];
double Fib5[MAXN+5];
int main(){
double t1,t2;
Fib1[1]=Fib1[2]=Fib2[1]=Fib2[2]=Fib3[1]=Fib3[2]=Fib4[1]=Fib4[2]=1;
Fib5[1]=Fib2[2]=1;
t1=clock();
for(int i=3;i<=MAXN;i++)
Fib1[i]=(Fib1[i-1]+Fib1[i-2])%MOD;
t2=clock();
printf("Time of 'int': %.4lf s\n",(t2-t1)/1000);
for(int i=3;i<=MAXN;++i)
Fib2[i]=(Fib2[i-1]+Fib2[i-2])%MOD;
t1=clock();
printf("Time of 'bool': %.4lf s\n",(t1-t2)/1000);
for(int i=3;i<=MAXN;++i)
Fib3[i]=(Fib3[i-1]+Fib3[i-2])%MOD;
t2=clock();
printf("Time of 'long long': %.4lf s\n",(t2-t1)/1000);
for(int i=3;i<=MAXN;++i)
Fib4[i]=(Fib4[i-1]+Fib4[i-2])%MOD;
t1=clock();
printf("Time of 'char': %.4lf s\n",(t1-t2)/1000);
for(int i=3;i<=MAXN;++i)
Fib5[i]=Fib5[i-1]+Fib5[i-2];
t2=clock();
printf("Time of 'double': %.4lf s\n",(t2-t1)/1000);
}
结果:
Time of ‘int’: 0.1280 s
Time of ‘bool’: 0.1120 s
Time of ‘long long’: 0.1770 s
Time of ‘char’: 0.1040 s
Time of ‘double’: 1.3360 s
##加 减 乘 除 模 位运算的运算速度
###加减乘除模
加减乘差不多,除法慢一点,模运算最慢(我猜是要做一遍除法和一遍减法):
#include<ctime>
#include<cstdio>
#define MAXN 100000000
#define TEST 100003
int main(){
double t1,t2;
int a=10000000;
t1=clock();
for(int i=1;i<=MAXN;i++,a=10000000)
a=a+TEST;
t2=clock();
printf("'+': %.4lf\n",(t2-t1)/1000);
for(int j=1;j<=MAXN;j++,a=10000000)
a=a-TEST;
t1=clock();
printf("'-': %.4lf\n",(t1-t2)/1000);
for(int i=1;i<=MAXN;i++,a=10000000)
a=a/TEST;
t2=clock();
printf("'*': %.4lf\n",(t2-t1)/1000);
for(int i=1;i<=MAXN;i++,a=10000000)
a=a*TEST;
t1=clock();
printf("'/': %.4lf\n",(t1-t2)/1000);
for(int i=1;i<=MAXN;i++,a=10000000)
a=a%TEST;
t2=clock();
printf("'%%': %.4lf\n",(t2-t1)/1000);
}
结果:
‘+’: 0.2620
‘-’: 0.2510
‘*’: 0.2580
‘/’: 0.3460
‘%’: 0.5290
###位运算
我只测了左移和乘 2 2 2的幂,好像没有什么区别。
#include<ctime>
#include<cstdio>
#define MAXN 100000000
#define MOD 1000000007
int main(){
double t1,t2;
int a=10000;
t1=clock();
for(int i=1;i<=MAXN;i++)
a=(a*1024)%MOD;
t2=clock();
printf("乘法: %.4lf\n",(t2-t1)/1000);
for(int i=1;i<=MAXN;i++)
a=(a<<10)%MOD;
t1=clock();
printf("位运算: %.4lf\n",(t1-t2)/1000);
}
英文写不下去了……
结果:
乘法: 0.9690
位运算: 0.9500
例……题
POJ-1742 Coins
https://vjudge.net/problem/POJ-1742
一份代码交HDU过,交POJ就T……
中间的绿是用旁边大佬的跟我一模一样的代码交的。
- 加读入优化:TLE
- 数组改到最小:TLE
int
数组改成bool
:AC
最初HDU上A了,POJ上T了的代码:
#include<cstdio>
#include<cstring>
#define MAXN 220000
int N,M,L;
int A[MAXN+5],C[MAXN+5];
int W[MAXN+5],dp[MAXN+5];
int main(){
while(1){
scanf("%d%d",&N,&M);
if(!N&&!M)
break;
for(int i=1;i<=N;i++)
scanf("%d",&A[i]);
for(int i=1;i<=N;i++)
scanf("%d",&C[i]);
L=0;
for(int i=1;i<=N;i++){
int k=1;
while(2*k<=C[i]){
W[++L]=k*A[i];
k<<=1;
}
W[++L]=(C[i]-k+1)*A[i];
}
memset(dp,0,sizeof dp);
dp[0]=1;
for(int i=1;i<=L;i++)
for(int j=M;j>=W[i];j--)
dp[j]|=dp[j-W[i]];
int Ans=0;
for(int i=1;i<=M;i++)
Ans+=dp[i];
printf("%d\n",Ans);
}
}
卡常A了后代码:
#include<cstdio>
#include<cstring>
inline int read(){
int x=0,f=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
return x*f;
}
#define MAXM 100
#define MAXN 100000
int N,M,L;
int A[MAXM+5],C[MAXM+5];
int W[MAXN+5];
bool dp[MAXN+5];
int main(){
while(1){
N=read(),M=read();
if(!N&&!M)
break;
for(int i=1;i<=N;i++)
A[i]=read();
for(int i=1;i<=N;i++)
C[i]=read();
L=0;
for(int i=1;i<=N;i++){
int k=1;
while(2*k<=C[i]){
W[++L]=k*A[i];
k<<=1;
}
W[++L]=(C[i]-k+1)*A[i];
}
memset(dp,0,sizeof dp);
dp[0]=1;
for(int i=1;i<=L;i++)
for(int j=M;j>=W[i];j--)
dp[j]|=dp[j-W[i]];
int Ans=0;
for(int i=1;i<=M;i++)
Ans+=dp[i];
printf("%d\n",Ans);
}
}