Trick
Trick
1.快速乘
解决乘法爆long long 的问题
int mul(int a, int b, int P){//快速乘
int L = a * (b >> 25ll) % P * (1ll << 25) % P;
int R = a * (b & ((1ll << 25) - 1)) % P;
return (L + R) % P;
}
其实就是利用了小学生都会的乘法分配律。
我们要计算 $ a*bmodp $,设 $ b=L+R,$
那么原式就变为为 \(( a*L~mod~p+a*R~mod~p )~mod~p\)
我们把 L 钦定为 b 的二进制前 x位,R为 b的后 (64-x) 位。
就得到了以上的代码(以上这份代码 x=25),复杂度近似为O(1)。
64位乘法
#include <iostream>
#include <cmath>
#include <cstdio>
#include <windows.h>
using namespace std;
long long a,b,p;
long long mul(long long a,long long b,long long p){
long long ans=0;
while(b){
if(b&1) ans=(ans+a)%p;
a=a*2%p;
b>>=1;
}
return ans;
}
int main(){
scanf("%lld%lld%lld",&a,&b,&p);
printf("%lld\n",mul(a,b,p));
return 0;
}
2.快读
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-'0';ch=getchar();}
return f*x;
}
快速输出
template<typename F>
inline void write(F x, char ed = '\n')
{
static short st[30];short tp=0;
if(x<0) putchar('-'),x=-x;
do st[++tp]=x%10,x/=10; while(x);
while(tp) putchar('0'|st[tp--]);
putchar(ed);
}
3.快速max,min
inline int min(int a,int b){return a<b?a:b}
inline void Max(int &x,int y){if(x<y)x=y;}
4.c++小知识
0x7fffffff int 类型的最大值
0x3f3f3f3f 是上面那个的一半
一般赋值都写成(防止上溢)
memset(s,0x3f,sizeof(s))
5.计算代码运行时间
#include<iostream>
#include<Windows.h>
using namespace std;
int main()
{
DWORD start_time = GetTickCount(); //开始时间; GetTickCount()获取从操作系统启动开始所经过的毫秒数,返回值是DWORD类型
for (int i = 0; i < 100000000; i++)
{
i++;
}
DWORD end_time = GetTickCount(); //结束时间;
cout << (end_time - start_time) << "ms" << endl;
return 0;
}
6.邻接表找反向边
初值tot=1;
然后 i^1就是反向边
edge(u,v)
for(int i=2;i<=tot;i+=2)
u=to[i],v=to[i^1];
7.memcpy
char a[100], b[50];
memcpy(b, a,sizeof(b));
//把a复制给b
//注意如用sizeof(a),会造成b的内存地址溢出
8.多起点一终点的推荐反着跑
9.scanf输入
scanf
long double %Lf
unsigned int %u
10.num[++num[0]]=x;
用num[0]计数,有多个数组的时候,不会弄混cnt名称
11.fix
当数组中可能遇见负数的时候,可以考虑采用修正值fix,将取值的区域平移。
12.区间中位数
二分一个中位数的值ans,大于ans的赋为1,小于-1(等于再说)
找区间内有无连续子段和大于0,判断ans+还是ans-
一些模板
大佬trick收集