一些简单的模板
一些简单的模板
快速幂模板
时间复杂度:\(O(\log b)\)
#include<bits/stdc++.h>
using namespace std;
long long a,b,p;
long long qp(long long a,long long b,long long p){
long long ans=1;
while(b){
if(b&1){//若b的当前最低二进制位为1
ans=ans*a%p;
}
a=a*a%p;
b>>=1;
}
return ans;
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>a>>b>>p;
cout<<a<<'^'<<b<<" mod "<<p<<'=';
cout<<qp(a,b,p);
return 0;
}
字符串哈希模板
时间复杂度:\(O(\sum M_{i}+N\log N)\)
#include<bits/stdc++.h>
using namespace std;
const long long mod1=1e9+7,mod2=1e9+9,base=131;
int N,ans=1;
string s;
pair<long long,long long> hashs[10005];//存储每个字符串的双哈希值
pair<long long,long long> Get(string s){//计算双哈希
long long h1=0,h2=0;
for(int i=0;i<s.size();i++){
h1=(h1*base+s[i])%mod1;
h2=(h2*base+s[i])%mod2;
}
return {h1,h2};
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>N;
for(int i=1;i<=N;i++){
cin>>s;
hashs[i]=Get(s);
}
sort(hashs+1,hashs+N+1);//排序,使相同的哈希对相邻
for(int i=1;i<N;i++){//统计个数
if(hashs[i]!=hashs[i+1]) ans++;
}
cout<<ans;
return 0;
}
线性筛素数模板
时间复杂度:\(O(n+q)\)
#include<bits/stdc++.h>
using namespace std;
const int N=1e8+5;
int n,q,k,cnt,pri[N],v[N];//v[i]记录i的最小质因子
void Get(){
for(int i=2;i<=n;i++){
if(!v[i]){//i没有被更小的质数筛掉,说明i是素数
pri[++cnt]=i;//存入素数表
v[i]=i;//素数的“最小质因子”就是它自己
}
for(int j=1;j<=cnt;j++){//用当前数i去筛掉合数i*pri[j]
//剪枝条件:
//1.如果pri[j]已经大于i的最小质因子,那么i*pri[j]的最小质因子不会是pri[j],此时跳出循环,保证每个合数只被其最小质因子筛一次
//2.乘积超出n范围,也直接停止
if(pri[j]>v[i]||1ll*pri[j]*i>n) break;
v[i*pri[j]]=pri[j];//记录i*pri[j]的最小质因子是pri[j]
}
}
}
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n>>q;
Get();
while(q--){
cin>>k;
cout<<pri[k]<<'\n';//第k个素数即pri[k]
}
return 0;
}
排序模板(基数排序)
时间复杂度:\(O(N)\)
#include<bits/stdc++.h>
using namespace std;
const int MAXN=1e6+5;
int N,a[MAXN],ta[65540],tt[MAXN],ans[100005];//计数数组,基数65536;临时数组,存放第一趟排序的结果
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>N;
for(int i=1;i<=N;i++) cin>>a[i];
//第一趟:按低16位排序
for(int i=1;i<=N;i++) ta[a[i]&0xffff]++;//统计低16位的出现次数
for(int i=1;i<65536;i++) ta[i]+=ta[i-1];//前缀和,使ta[x]表示低16位<=x(0~65535)的元素个数
//逆序遍历原数组,稳定地放入临时数组tt;a[i]&0xffff:当前元素的低16位;
for(int i=N;i>=1;i--) tt[ta[a[i]&0xffff]--]=a[i];//放入对应桶的末尾,并减少计数
//第二趟:按高16位排序
memset(ta,0,sizeof(ta));//清空计数数组
for(int i=1;i<=N;i++) ta[tt[i]>>16]++;//统计高16位的出现次数(注意此时遍历的是tt,已经按低16位排好)
for(int i=1;i<65536;i++) ta[i]+=ta[i-1];//前缀和
//逆序遍历tt,稳定地放入最终数组ans
for(int i=N;i>=1;i--) ans[ta[tt[i]>>16]--]=tt[i];//tt[i]>>16:当前元素的高16位
for(int i=1;i<=N;i++) cout<<ans[i]<<' ';//输出
return 0;
}
数列离散化模板
时间复杂度:\(O(Tn\log n)\)
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int T,n,a[N],rk[N];
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>T;
while(T--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
rk[i]=a[i];//备份原始值,用来查找排名
}
sort(a+1,a+n+1);//1.对原数组排序
int cnt=unique(a+1,a+n+1)-a-1;//2.去重,cnt是不同值的个数
for(int i=1;i<=n;i++){//3.对每个原始值,在有序去重数组中二分查找其位置(=排名)
rk[i]=lower_bound(a+1,a+cnt+1,rk[i])-a;//lower_bound返回第一个>=rk[i]的地址,减去a(首地址)得到1‑based排名
}
for(int i=1;i<=n;i++) cout<<rk[i]<<' ';//输出
cout<<'\n';
}
return 0;
}
快速读入模板
#include<bits/stdc++.h>
using namespace std;
long long n,sum;
long long read(){
long long k=0,f=1;//k:存储读取的数值;f:符号标记
char c=getchar_unlocked();//一次读入一个字符,绕过锁加速(平时还是建议用getchar(),但本题卡常)
while(c<'0'||c>'9'){//跳过非数字字符,同时判断符号
if(c=='-') f=-1;//检测到负号
c=getchar_unlocked();
}
while(c>='0'&&c<='9') k=k*10+c-'0',c=getchar_unlocked();//连续读入数字,按十进制累加
return k*f;
}
void wrt(long long x){
if(x<0) putchar('-'),x=-x;// 处理负数
if(x<10) putchar(x+'0');//如果是一位数,直接输出
else wrt(x/10),putchar(x%10+'0');//递归输出(先输出高位)
}
int main(){
n=read();
while(n--) sum+=read();
wrt(sum);
return 0;
}
栈模板
#include<bits/stdc++.h>
using namespace std;
int T,n;
unsigned long long x;
string t;
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>T;
while(T--){
stack<unsigned long long> s;
cin>>n;
while(n--){
cin>>t;
if(t=="push"){
cin >> x;
s.push(x);
}else if(t=="pop"){
if(s.size())s.pop();
else cout<<"Empty\n";
}else if(t=="query"){
if(s.size()) cout<<s.top()<<'\n';
else cout<<"Anguei!\n";
}else{
cout<<s.size()<<'\n';
}
}
}
return 0;
}
队列模板
#include<bits/stdc++.h>
using namespace std;
int n,x;
queue<int> q;
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>n;
while(n--){
cin>>x;
if(x==1){
int x1;cin>>x1;
q.push(x1);
}
else if(x==2){
if(q.empty()){
cout<<"ERR_CANNOT_POP"<<'\n';
}
else q.pop();
}
else if(x==3){
if(q.empty()){
cout<<"ERR_CANNOT_QUERY"<<'\n';
}
else cout<<q.front()<<'\n';
}
else{
cout<<q.size()<<'\n';
}
}
return 0;
}
双端队列1模板
#include<bits/stdc++.h>
using namespace std;
list<int> q[1000005];//deque的静态空间较大无法通过本题,但注意list(及类似链表实现)的时间常数较大
int p,a,x;
string s;
int main(){
ios::sync_with_stdio(0);cin.tie(0);
cin>>p;
while(p--){
cin>>s;
if(s=="push_back"){
cin>>a>>x;
q[a].push_back(x);
}
if(s=="pop_back"){
cin>>a;
if(q[a].size()) q[a].pop_back();
}
if(s=="push_front"){
cin>>a>>x;
q[a].push_front(x);
}
if(s=="pop_front"){
cin>>a;
if(q[a].size()) q[a].pop_front();
}
if(s=="size"){
cin>>a;
cout<<q[a].size()<<'\n';
}
if(s=="front"){
cin>>a;
if(q[a].size()) cout<<q[a].front()<<'\n';
}
if(s=="back"){
cin>>a;
if(q[a].size()) cout<<q[a].back()<<'\n';
}
}
return 0;
}

浙公网安备 33010602011771号