• 奇迹银桥「2」


    上回反响不行啊……

    这会Miemeng要给大家三个考试技巧!

    1.‘#’系列(预处理器)

    #if
    #ifdef
    #ifndef
    #elif
    #endif
    #undef
    #define
    

     上面这些非常有用!

    我们主要说一下 #ifdef 这样的(有用!)

    考试时往往要开 freopen 于是有人忘了,有人不习惯文件输入输出

    所以用下面的代码片:

    #include <bits/stdc++.h>
    
    using namespace std;
    
    int main(){
    #ifndef LC   
    /*LC 也可以写自己喜欢的变量名*/
        freopen("*.in" ,"r",stdin);
        freopen("*.out","w",stdout);
    #endif
    /*照常打代码*/
    }
    

     稍稍解释一下:

     #if 就类比于 if ,只是针对编译器起作用,意思就是说后面是 true 就编译下面的语句(不要以为你可以在后面加一个变量)

    于是 #endif 是结束这个过程(一个 if 管全局要命啊)

    那么 #ifdef  就是另一个版本,意思是说后面的宏(可以理解为一个常量)被定义了,就编译下面的语句

     #ifndef 就是$if not define$,可以理解是上面的取非。

     #elif 就很好理解了吧,就是类似$else \, if$的东西

    如果要和 #ifdef 一起用还要写个 #elif defined A (如果上面的未定义却定义了A,就编译下面的语句,否则跳过跳到 #endif )

    说这么大一坨其实也没啥用

    下面说一个必须要知道的东西:

    当你使用了上面的代码片后,$g++$编译,你就会发现它还是文件输入输出(不要打我啊,还没有说完)(别打脸……啊)

    因为你并没有定义$LC$所以还是没法跳过 freopen ,

    于是用下面的$g++$编译

    g++ file.cpp -o file -D LC
    

    后面的 -D LC 非常好理解啊,就是在编译时定义一下$LC$

    发现还有一个#undef

    与#define 相对

    将后面的宏解除定义

    #include <iostream>
    #define N 123
    
    using namespace std;
    
    int main(){
    	cout<<N<<endl;//输出123
    #undef N
    	cout<<N<<endl;//这里会告诉你N没定义
    }
    

    剩下的就是没啥用的了:

    #error
    #warning
    #pragma
    

     #pragma大家应该都明白是什么……

    这里说一个:message("sting")

    用法:

    #pragma message( "输出一条Note!" )
    

    作用?也许并没有

    #error是好东西(虽然没有什么用)

    #error 输出一条error,不写引号也可以!
    

     #warning就不好用了,它只能控制警告的输出QwQ(所以根本没有用)

    至于到底怎么用,去$C++$手册

    2.文件流 & 字符串流

    别以为名字很高大上就很厉害,其实和第一课学的$cin$ $cout$是兄弟

    文件流:

    调库:

    #include <fstream>
    

     定义:

    fstream a,b,c,d;
    

    使用:

    首先打开文件:

    a.open("文件名",/*参数*/ios_base::in);
    

     后面的参数有下面几种:

    ios_base::in //输入(类比与cin)
    ios_base::out //输出 (类比与cout)
    ios_base::app//在文件的末尾cout (不新建文件)
    

     所以给个例子:

    #include <bits/stdc++.h>
    #define N 101010
    using namespace std;
    
    void ran(){
    	int l,c,qn;
    	fstream rin,rout;
    	rin.open("std",ios_base::in);
    	rout.open("vegetable.in",ios_base::out);
    	rin>>l>>c>>qn;
    	rout<<l<<" "<<c<<" "<<qn<<endl;
    	for(int i=1;i<=l;i++){
    		for(int j=1;j<=c;j++){
    			rout<<rand()%100000<<" ";
    		}rout<<endl;
    	}
    	for(int i=1;i<=qn;i++){
    		int a=rand()%l+1,b=rand()%c+1,
    			c=rand()%l+1,d=rand()%c+1;
    		rout<<min(a,c)<<" "<<min(b,d)<<" "<<max(a,c)<<" "<<max(b,d)<<endl;
    	}rout<<endl;
    }
    int main(){
    	int T=N;
    	srand(time(0));
    	//ran();return 0;
    	while(T--){
    		if(T%10000==0)srand(time(0));
    		ran();
    		system("time ./ac");
    		system("./bl");
    		if(system("diff ac.out bl.out")){
    			puts("WA");
    			return 0;
    		}
    		cout<<T<<"/"<<N<<"AC"<<endl;
    	}
    }
    

     所以研究一番代码,发现这是把ran直接揉到对拍里写的

    有什么好处?

    1. 可以把一个随机数时间种子充分利用,比如上面的代码中每个种子中,随机数用了10000次
    2. 可以实时控制对拍进程,发现可以再开一个流输入数据参数,于是可以在一次对拍中随时更改数据范围……

    字符串流:

    调库:

    #include <sstream>
    

     定义:

    stringstream q;
    

     使用:

    就是把一个数输到字符串里,或是从字符串里读出一个数

    (没啥用,而且特特特特特特特特特特别慢)

    具体例子可以看这个一件建文件的代码(别乱改,容易爆,或者先把死循环打掉)

    #include <bits/stdc++.h>
    using namespace std;
    string p,x;
    int main(){
    	fstream init;
    	init.open("Number.pre",ios_base::in);
    	if(init.is_open()){
    		init>>p>>x;
    	}
    	else {
    		init.close();
    		init.open("Number.pre",ios_base::out);
    		init.close();
    		init.open("Error",ios_base::out);
    		init<<"Need A File Named Number.pre
    A *.pre file is for File name"<<endl;
    		init.close();
    		return 0;
    	}
    	for(int i=0;;i++){
    		stringstream q;
    		string k;
    		q<<i;
    		q>>k;
    		k=p+k+x;
    		fstream a;
    		a.open(k.c_str(),ios_base::in);
    		if(a.is_open()){
    			a.close();
    		}
    		else{
    			fstream b;
    			b.open(k.c_str(),ios_base::out);
    			b.close();
    			return 0;
    		}
    	}
    }
    

     3.STL的一点点骗分技巧

    mt19937

    基于梅森缠绕器算法,可以产生循环节长达$2^{19937}$的随机数(至于梅森缠绕器,我也不知道那是啥)

    用法?和 rand() 一样

    Upd:mt19937适用于值域在整个实数域的$[-Inf,+Inf]$,因为能产生均匀的正数和负数。

    调库:

    #include <random>
    

     使用:

    #include <bits/stdc++.h>
    
    using namespace std;
    mt19937 ran(time(0));
    int main(){
    	cout<<ran()<<endl;
    }
    

     好简单啊~~记得开C++11

    数据结构(杂)

     vector 可以 reserve 来分配内存防止它倍增到你MLE

    #include <bits/stdc++.h>
    
    using namespace std;
    vector<int>k;
    int main(){
    	k.reserve(100);
    }
    

      unordered_map 是基于 hash 的$O(1)$查询map

    #include <unordered_map>
    
    using namespace std;
    unordered_map<int,int>k;
    int main(){
    	k.rehash(100);
    }
    

     P.S. 别忘了开C++11


     完结了,累死了……

    可能不会再更了(倾出了毕生绝学)

  • 相关阅读:
    python 编码问题
    关于网页划词翻译
    clang 编译 c++
    Java流(Stream)操作实例筛选、映射、查找匹配
    JAVA系列笔记十八之nohup实现后台运行程序
    VSCode汇总
    java jdk 国内下载镜像地址及安装
    LocalDate、LocalDateTime与timestamp、Date的转换
    List.sort()排序功能
    Java Array、List、Set互相转化
  • 原文地址:https://www.cnblogs.com/kalginamiemeng/p/QJYQ2.html
Copyright © 2020-2023  润新知