\(\text{Point 1}\)

可以用 memset(f,0x3f,sizeof f) 来给 \(\text{int},\text{long long}\) 极大值赋值,它的两倍也不会爆。

可以用 memset(f,0x7f,sizeof f) 来给 \(\text{int},\text{long long}\) 极大值赋值,不过它的两倍会爆。

可以用 memset(f,0xc0,sizeof f) 来给 \(\text{int},\text{long long}\) 极小值赋值,它的两倍也不会爆。

可以用 memset(f,0x80,sizeof f) 来给 \(\text{int},\text{long long}\) 极小值赋值,不过它的两倍会爆。


\(\text{Point 2}\)

求二进制中 \(1\) 的个数。

方法壹

__builtin_popcount(x),头文件 #include <cstdio>

方法贰

递推有 rep(i,1,n) bit[i]=bit[i-(i&-i)]+1;

\(\text{Point 3}\)

二进制枚举子集,假设 \(\rm lim\) 的二进制有 \(n\) 位。

for(int s=0;s<=lim;++s)
    for(int i=s;i;i=(i-1)&s)

每次都在减小,而 &s 保证了一定是子集,故正确。

关于时间复杂度就是 \(\mathcal O(3^n)\)

首先对于有 \(i\)\(1\) 的数,因为枚举是只枚举子集且只枚举一次,时间复杂度就是 \(1\) 可以变成 \(1/0\)\(\mathcal O(2^i)\)

而我们有 \(C_n^i\) 个这样的数,总时间复杂度为 \(\mathcal O(\sum_{i=0}^n C_n^i\times 2^i\times 1^{n-i})=\mathcal O(3^n)\)

\(\text{Point 4}\)

这样好像会快一点。

inline int mul(const int x,const int y) {return 1ll*x*y-1ll*x*y/mod*mod;}

\(\text{Point 5}\)

快速判断一个数是否为 \(2\) 的幂。即 ((x-1)&x)=0.

正负号转换:x = (~x)+1.

比较数值是否同号:(x^y)>0.

附加一些 \(\mathtt{qqgg}\) 的数:

\[\text{0xaaaaaaaa} = 10101010101010101010101010101010 \\ \text{0x55555555} = 1010101010101010101010101010101 \\ \text{0x33333333} = 110011001100110011001100110011 \\ \text{0xcccccccc} = 11001100110011001100110011001100 \\ \text{0x0f0f0f0f} = 00001111000011110000111100001111\\ \text{0xf0f0f0f0} = 11110000111100001111000011110000 \]


\(\text{Point 6}\)

哈希表模板:

struct hash_table {
	int head[key],cnt;
	struct Edge {
		ull val; int to;
	} e[maxn];
	
	void Insert(ull x) {
		e[++cnt].val=x,e[cnt].to=head[x%key],head[x%key]=cnt;
	}
	
	bool Count(ull x) {
		for(int i=head[x%key];i;i=e[i].to)
			if(e[i].val==x) return 1;
		return 0;
	}
} mp;

似乎表大小开元素个数 \(4\) 倍比较稳。另外注意求哈希值的时候,选取的模数要远大于方案数。


\(\text{Point 7}\)

max_element()min_element()

  1. 时间复杂度为 \(\mathcal O(n)\)
  2. 数组从 \(1\) 开始时,只用减去数组名。
  3. 当返回下标时,返回的是原数组的值按照规定排序后 去重 的下标。比如 1 2 3 3 2

\(\text{Point 8}\)

\(\rm spfa\) 判断负环(起点 可到达 的负环):存储从起点到达这个点 成功扩展 了几次,如果有 \(n\) 次说明一定存在被经过两次的点,就形成了一个环。考虑我们在求取最短路,如果这个环不是负环就一定不优,所以此图存在负环。


\(\text{Point 9}\)

关于 nth_element()。求第 \(k\) 小的同时将小的放在左边,大的放右边,保证第 \(k\) 位为第 \(k\) 小。不保证 时间复杂度为 \(\mathcal O(n)\)

使用方法:nth_element(a+start,a+k,a+end+1)。还可以自定义排序。


\(\text{Point 10}\)

fep(i,30,0) if(ans+(1<<i)<=1e9 && ok(ans+(1<<i))) ans+=(1<<i);

二分 \(1e9\) 内满足条件的最大值。


\(\text{Point 11}\)

这个 \(\rm trick\) 好像没啥大用(自己应该不会把题目做到需要卡常的分数),但还是想记录下来:比方说计算某个编号在一棵线段树上是第几层的第几个点,显然只用算出小于等于这个数的最大的 \(2\) 的幂。计算这个可以用两种方法:

\(\mathcal O(\log \log n)\)

inline int getId(int o) {
    o |= (o>>1);
    o |= (o>>2);
    o |= (o>>4);
    o |= (o>>8);
    o |= (o>>16);
    return o+1>>1;
}

假设最高位的 \(1\) 在第 \(i\) 位,我们要做的是将后面到第 \(0\) 位都变成 \(1\),这样加一再除二就是答案。

\(\mathcal O(1)\)

预处理出 \(\log_i\),直接 \(2^{\log_i}\) 即可。


\(\text{Point 12}\)

__builtin_ffs(x)\(x\) 二进制最后一个 \(1\) 在从右往左数的第几位。


\(\text{Point 13}\)

进行多次取模时,可将变量改成 long long 类型来减少取模次数。


\(\text{Point 14}\)

无限栈:

-Wl,--stack=128000000

忽略空格的 \(\rm checker\)

system("fc /W palin.out palin4.ans")

有的时候,文件输入输出后需要在控制台操作,咋办呢?可以这样写:

int main() {
	freopen("data.in","r",stdin);
	freopen("result.out","w",stdout);
	int a,b;
	scanf("%d %d",&a,&b);
	printf("%d\n",a+b);
	freopen("CON","r",stdin);
	freopen("CON","w",stdout);
	cin>>a>>b;
	printf("%d\n",a+b);
	return 0;
}

关闭文件可以用 fclose() 函数。


\(\text{Point 15}\)

遇见 \(n\times m\le 10^5\) 的题目该怎么存下数组呢?

当然是,\(\rm vector\)T 成什么东西就不用我多说了吧。

事实上,你也可以使用 new 这个玩意

当然,二维数组可以这样搞:

int **a;
a=new int*[n];

不过好像在 \(\rm Linux\) 环境下写 delete() 会内存超限。


\(\text{Point 16}\)

存一下各种颜色的字体:

<font color= #F8F8FF>写点东西。</font>

另外还有设置图片居中:

<div align=center>
<img src="链接"/>
</div>

\(\text{Point 17}\)

关于 \(\rm bitset\) 的一些函数:

  • set(x,y)。将第 \(x\) 位置为 \(y\)
  • _Find_first()。从低位到高位找到第一个 \(1\) 的位置。如果没有返回 \(\rm bitset\) 大小。复杂度是 \(\mathcal O(n/w+cnt_1)\)
  • _Find_next(x)。就是找到 \(x\) 位置的下一个 \(1\) 的位置。复杂度是 \(\mathcal O(n/w+cnt_1)\)

\(\text{Point 18}\)

还记得在读入优化中这条语句吗?

while(s>='0' and s<='9')
    x=(x<<1)+(x<<3)+(s^48),
	s=getchar();

为什么 s^48 能将字符转成数字呢?首先字符 \(0\)\(\rm ASCII\) 码是 \(48=2^5+2^4\),由于字符 \([0,9]\) 远没有达到 \(2^4\) 这一位,所以可以直接异或 \(48\)

同理,我们可以优化大小写转化。由于 \(a,A\)\(\rm ASCII\) 码分别是 \(97=2^6+2^5+2^0,65=2^6+2^0\),而且 \(26\) 个字母没有 \(32\) 大,所以直接异或 \(32\) 即可。


\(\text{Point 19}\)

使用 \(\rm cmd\) 计算 静态 内存。\(\text{Link.}\)


\(\text{Point 20}\)

有符号整数溢出是未定义行为,较高版本编译器不会考虑这种情况。

可以加个 -fsanitize=undefined 来检测一些未定义行为。


\(\text{Point 21}\)

关于 memcpy(s,begin,len)。表示从 \(\rm begin\) 开始的地址复制 \(\rm len\)\(s\)


\(\text{Point 22}\)

吃个 \(\rm fread\)

char buf[1<<21];
inline char gc() {
	static char *S=buf,*T=S;
	if(S==T) S=buf,T=S+fread(S,1,1<<21,stdin);
	return *(S++);
}

\(\text{Point 23}\)

关于 fgets(char *str,int num,FILE *stream)\(\rm str\) 是被拷贝数组的起始指针,\(\rm num\) 是想要读取的元素个数 \(+1\),后面那个用 stdin 即可。

停止条件:

  • 拷贝完规定字符。但不到换行符或 \(\text{End Of File}\) 不会停止读入。
  • 到换行符或 \(\text{End Of File}\)

需要注意,如果读入到换行符时未读入完规定字符,会将 \n 插入字符串末并计入长度。

返回值:如果到达文件末尾或者没有读取到任何字符或者发生错误,返回一个空指针 \(\rm null\).


\(\text{Point 24}\)

\(\rm cmd\) 编译运行 \(\text{C plus plus}\) 程序:

  • \(\rm mingw\) 中的 \(\rm bin\) 设置在系统变量的 \(\rm path\) 中。
  • cd 转到目录(可以用 cd /d D:\),然后输入 g++ -o name name.cpp -std=c++14
  • 最后输入 name.exe

\(\text{Point 25}\)

有时候乘法取模连 \(\text{unsigned long long}\) 都会溢出。怎么办?龟速乘?

事实上,我们可以运用乘法分配律!

inline ll ksc(ll x, ll y, ll P){
    ll L = x*(y>>25)%P*(1<<25)%P;
    ll R = x*(y&((1<<25)-1))%P;
    return (L+R)%P;
}

\(\text{Point 26}\)

\(\rm vector\) 如何真正释放内存?

vector <TYPE> ().swap(myVector)


\(\text{Point 27}\)

\(\rm Kahan\) 求和:原理代码

需要注意应该先减去较大值。


\(\text{Point 28}\)

正则表达式删除代码行号:\(\rm Link.\)


\(\text{Point 29}\)

cin.getline(char *str,int num,结束符(char)):此时 \(\rm num\) 仍然是想要读取的元素个数 \(+1\),但如果读入到结束符时未读入完规定字符也不会插入其它字符。它会用空字符替换结束符。

一个需要注意的点是 cin.getline()getline()getchar() 等都是在缓冲区读入,这次没读完的下次还会继续读。

再记录一个输入超长的问题:

char a[20];
cin.getline(a,5); // 输入:12345(enter)
cout<<a<<endl;
char ch=getchar();
cout<<ch<<endl;

显然 \(a\) 输出的值是 1234,但你会发现 \(\rm ch\) 读不进 5!这是因为 cin.getline() 输入超长时,会引起 cin 函数的错误,后面的 cin 操作将不再执行。解决方法是使用 cin.clear(),重置错误标志。


getline(FILE *stream,string& str,结束符(char)):如果读入到结束符时未读入完规定字符也不会插入其它字符。它会用空字符替换结束符。


\(\text{Point 30}\)

偷懒可以直接用 \(\text{pb_ds}\) 里的 \(\text{hash_table}\),用法和 \(\rm map\) 基本相同,但是会快一些:

# include <ext/pb_ds/hash_policy.hpp>
# include <ext/pb_ds/assoc_container.hpp>

然后再用

__gnu_pbds::gp_hash_table <TYPE, TYPE> map;

\(\text{Point 31}\)

存一下在 \(\rm linux\) 环境下的对拍程序。

\(\rm datamaker.cpp\)

# include <cstdio>
# include <cctype>
# define print(x,y) write(x), putchar(y)

template <class T>
inline T read(const T sample) {
    T x=0; char s; bool f=0;
    while(!isdigit(s=getchar())) f|=(s=='-');
    for(; isdigit(s); s=getchar()) x=(x<<1)+(x<<3)+(s^48);
    return f? -x: x;
}
template <class T>
inline void write(T x) {
    static int writ[50], w_tp=0;
    if(x<0) putchar('-'), x=-x;
    do writ[++w_tp]=x-x/10*10, x/=10; while(x);
    while(putchar(writ[w_tp--]^48), w_tp);
}

# include <unistd.h>
# include <bits/stdc++.h>
using namespace std;

int main() {
	usleep(1000.0);
	int n=15, tot=0, x; print(n,'\n');
	mt19937 SEED(time(0));
	uniform_int_distribution <int> mac(0,1);
	for(int i=1;i<=(n<<1);++i) {
		if((n<<1)-i+1==tot) {
			for(int j=1;j<=tot;++j)
				putchar('b');
			break;
		}
		while(233) {
			x = mac(SEED);
			if(tot==0 && x);
			else break;
		} putchar(x? 'b': 'a');
		tot += x? -1: 1;
	} puts("");
	return 0;
}

\(\rm checker.cpp\)

# include <cstdio>
# include <cctype>
# define print(x,y) write(x), putchar(y)

template <class T>
inline T read(const T sample) {
    T x=0; char s; bool f=0;
    while(!isdigit(s=getchar())) f|=(s=='-');
    for(; isdigit(s); s=getchar()) x=(x<<1)+(x<<3)+(s^48);
    return f? -x: x;
}
template <class T>
inline void write(T x) {
    static int writ[50], w_tp=0;
    if(x<0) putchar('-'), x=-x;
    do writ[++w_tp]=x-x/10*10, x/=10; while(x);
    while(putchar(writ[w_tp--]^48), w_tp);
}

# include <bits/stdc++.h>
using namespace std;

int main() {
    for(int i=1;i<=1000;++i) {
        system("./datamaker > data.in");
        system("./1 < data.in > 1.out");
        system("./2 < data.in > 2.out");
        if(system("diff 1.out 2.out"))
            { printf("\033[0m\033[1;31mWrong Answer.\033[0m\n"); return 0; }
        else printf("\033[0m\033[1;32mAccepted.\033[0m\n");
    }
    return 0;
}
posted on 2020-02-20 15:58  Oxide  阅读(259)  评论(5编辑  收藏  举报