您的位置:首页 > 其它

【颓废/学术/综合篇】小(hei)技(ke)巧(ji) 随时看心情更新哦~

2017-06-14 20:51 316 查看
一些奇怪的小科技,不一定有什么大用场,就是收集一下~

1.随机生成L~R间的实数:

double The_Rand(double L,double R) {
return rand() / (RAND_MAX*1.0)*(R - L) + L;
}


其中,

rand() / (RAND_MAX*1.0)


就可以产生0~1的随机实数了= =

2.快速读入:

scanf读入还要判断格式字符,比较慢,cin更不必说= =

我们已知读入的一定是整数(或者特定的字符),我们就可以利用飞快的getchar(void)来达到快速输入的目的!

代码(早已烂熟,这样应该是跑的比较快的)(写的码风很奇特大家轻喷):

int getchar(){
int a=0;char c=getchar();bool f=0; //f用来判断负数
for(;(c<'0'||c>'9')&&c!='-';c=getchar());//isdigit速度不明
if(c=='-') f=1,c=getchar();
for(;c>='0'&&c<='9';c=getchar()) a=(a<<1)+(a<<3)+c-'0';
if(f) return -a; return a;
}//返回值就是读进来的整数..


3.经实验,最快的max是:

inline int max(const int &a,const int &b){
if(a>b) return a; return b;
}


而define党们为了避免不必要的冲突,可以看一下自带max的define方法(这里用VS2015的define)

(((a)>(b))?(a):(b))


4.对拍的写法

I 写一个随机的数据生成器,里面加上

freopen("data.in","w",stdout); //第一个文件名无所谓,开心就好


II 找两个拿来对拍的cpp,分别是正确的(暴力or标程)和不一定正确的(自己的代码)

里面分别加上

freopen("data.in","r",stdin); //两个文件都加
freopen("sb.out","w",stdout); //不一定正确的,文件名搞笑的
freopen("smart.out","w",stdout); //正确的,文件名还是搞笑的


然后编译出exe

III 核心部分,代码(没事挺好记的)

#include <cstdlib>
int main(){
while(1){
system("smart.exe"/*正确的*/);
system("sb.exe"/*不一定正确的*/);
if(system("fc smart.out sb.out")) {//cmd指令比较文件,如果不一样
system("pause");
//MessageBox("You fool,the program is wrong!"); //极尽嘲讽(这句是伪代码)
}
}
}


反正差不多就这样就行了= =

5.MessageBox的用法(不在类中的):

函数原型:

MessageBox(HWND hWnd,LPCTSTR lpText,LPCTSTR lpCaption,UINT uType);


其实是根据Unicode定义的~

//好吧我承认这段是从baidu复制来的
WINUSERAPI int WINAPI MessageBoxA(
HWND hWnd,
LPCSTR lpText,
LPCSTR lpCaption,
UINT uType);

WINUSERAPI int WINAPI MessageBoxW(
HWND hWnd,
LPCWSTR lpText,
LPCWSTR lpCaption,
UINT uType);

#ifdef UNICODE
#define MessageBox MessageBoxW
#else
#define MessageBox MessageBoxA
#endif


第一个参数指窗口(不知道的写NULL就行_ (:з」∠) _),第二个是内容,第三个标题(NULL的话会默认成Error/错误),第四个是类型(NULL则默认为MB_OK))

如果只想写一个提示框,那就

MessageBox(NULL,"Hello, World","From Enzymii",NULL);


如果想加一些特定的选项并为之响应(以MB_YESNOCANCEL为例,其他同理)

int Ans=MessageBox(NULL,"Hello, World!","From Enzymii",MB_YESNOCANCEL);
switch(Ans){
case IDYES:    //点YES的处理
break;
case IDNO:     //点NO的处理
break;
case IDCANCEL: //点CANCEL的处理
break;
}


就这样啦~很简单呢~

然后再附一张MessageBox的类型图(也来自baidu~)



6.手动优化

在OJ中被卡常数?OJ时限不合理,导致无法AC?跟好友压常大赛?

众所周知,O2啊O3啊这些优化能大大加快程序的效率(当然作用有限),而很多OJ中不是不打开优化开关的(O0)不过我们可以开手动优化哦~

(当然这不利于自己水平的提高,建议大家谨慎使用)(比如可以用floyd艹掉nlogn的题)

代码很短 (以O3为例)

#pragma comment optimize (3)


好像还有很多种写法能达到同样的效果= =

当然luogu(可能还有别的)是屏蔽掉#pragma的,所以

#pr\
agma comment optimize (3)


哈哈哈~

7.运算符优先级

丁队说自己大考前都要背一遍C++运算符的优先级。。

所以非常的重要。。。。

先贴个网址:传送门(英文预警)

其实是一目了然的……(毕竟可以不看英文只看符号对不对)

大家收藏一下就行了,我不需要整理吧……

8.虚拟键码表

【颓废专用】这个在OI上似乎一点用都没有。

基本就是自己备查(也是因为再懒得找)

很懒,所以搬来一个传送门。银月城传送门~

9.离散化的一种写法

STL依赖症……强行利用vector进行离散化= =

比如说我们要读入c[i]数组,然后对其进行离散化,可以这么写:

vector<int> vec;    //如果vector可能会大的话最好开全局???
//读入元素并放到vector中
for(int i=1;i<=n;i++) c[i]=getnum(),vec.push(c[i]); //我就是写快读了怎么着吧~
//将vector排序并去重(unique会将重复的元素扔到容器后面然后返回第一个重复元素所在的迭代器)
sort(vec.begin(),vec.end()); vec.erase(unique(vec.begin(),vec.end()),vec.end());
//然后对于每个元素利用lower_bound查找到其位置即可...
c[i]=(lower_bound(vec.begin(),vec.end(),c[i])-vec.begin())+1;   //这样就是从1开始的编号了


时间复杂度O(nlogn+STL常数)

我们如果要查找离散前的值,从vector里扒出来即可:

int num=vec[c[i]-1];    //你要是上面用从0开始的编号(不+1)这里就不用-1了orz


其实一点都不难2333

10.SPJ_for_Lemonの写法

既然裱过了吃枣药丸的辣鸡出题人, 作为有出水题梦想的人 我们还是要学习一下spj的写法的…

不过令人头疼的是, 各地方的spj写法是不一样的…

这里介绍一下lemon的spj的写法…

lemon是通过main函数的argv列表来确定各个文件的…

- argv[1]输入文件

- argv[2]选手输出文件

- argv[3]标准输出文件

- argv[4]测试点分数

- argv[5]测试点得分

- argv[6]测试点信息

确定了这一点之后, 我们就可以用非常标准的文件操作来搞了…(这里我用C的方式了哦)

建立一个cpp文件, 将其命名为checker.cpp

首先定义一些变量:

FILE *fin/*输入文件*/,*fout/*选手输出*/,*fstd/*标准输出*/,*fpts/*得分*/,*fstr/*信息*/;
int point; /*测试点分数*/


然后主程序就可以这么写..

int main(int args,char* argv[]){
fin=fopen(argv[1],"r");
fout=fopen(argv[2],"r");
fstd=fopen(argv[3],"r");
fpts=fopen(argv[5],"w");
fstr=fopen(argv[6],"w"); //打开这些文件,注意打开方式..
point=atoi(argv[4]); //将字符串转为数字..
spj();
fclose(fin);
fclose(fout);
fclose(fstd);
fclose(fpts);
fclose(fstr);
}


然后spj函数自定义一下就行了OvO

比如需求如果是这样:

所得到的结果是一个浮点数. 当选手输出与标准输出相差不超过10−6时,能得到该测试点的全部分数;当选手输出与标准输出相差不超过3∗10−5时,能得到该测试点的40%的分数.

那我们就可以这样写(当然这里吸取了一些教训,加了一些别的…)

void spj(){
double ans,out,cha;
fscanf(fstd,"%lf",&ans); //获取标准输出的值
int ret=fscanf(fout,"%lf",&out);
//这里判断一定是EOF而不是0. 不然不输出没准都能得分...
if(ret==EOF){
fprintf(fstr,"WA:Input Error!"); //将结果写入信息文件(这里可以抖机灵...
fprintf(fpts,"%d",0); //将分数写入得分文件(这里可以打出比满分高的分数OvO
return; //都没输出了就别评了,退出吧←_←
}
//这里是看一下有没有Too Long...
char strs[1001];
ret=fscanf(fout,"%s",strs);
if(ret!=EOF){
fprintf(fstr,"WA:Too Long!");
fprintf(fpts,"0");
return; //这里与上面输入错误同理
}
cha=out-ans; //计算选手输出与标准输出的差
if(fabs(cha)<1e-6){
fprintf(fstr,"AC");
fprintf(fpts,"%d",point);
}
else if(fabs(cha)<3e-5){
fprintf(fstr,"PC:Excepted:%6lf Get:%6lf",ans,out); //信息怎么写都行...printf会用吧?
fprintf(fpts,"%d",(int)(point*0.4));
}
else{
fprintf(fstr,"WA:Excepted:%6lf Get:%6lf",ans,out);
fprintf(fpts,"%d",0); //WA和PC同理嘛...
}
}


编译出exe扔到data的题目(加入题目名为Problem)文件夹里..

然后题目里选自定义检验器(这里应该贴图的)

在下面的白框里面输入Problem/checker.exe

然后就可以愉快的评测了OvO…

希望大家都能成为良心的出题人…

别的想起来再更新吧= =此贴不结= =
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: