一些进制,日期的计算方法
- 电脑带的计算器也是很实用的
bitset
- 求二进制的函数
#include<iostream>
#include<bitset>
using namespace std;
int main(){
int n,m;
while(cin>>n>>m){
bitset<8> t(n);//8:指定几位数
bitset<8> tt(m);
cout<<t<<endl<<tt<<endl;
}
return 0;
}
二维数组前缀和
https://www.acwing.com/problem/content/101/
#include<bits/stdc++.h>
#define maxn 5010
using namespace std;
int N,R,ans=1,sum=0;
int a[maxn][maxn];
int main(){
cin>>N>>R;
int n=R,m=R;
for(int i=0,x,y,z;i<N;i++){
cin>>x>>y>>z;
x++;y++;n=max(n,x);m=max(m,y);
a[x][y]+=z;
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
}
}
int ans=0;
for(int i=R;i<=n;i++){
for(int j=R;j<=m;j++){
ans=max(ans,a[i][j]-a[i][j-R]-a[i-R][j]+a[i-R][j-R]);
}
}
cout<<ans;
return 0;
}
01背包
for(int i=1;i<=n;i++){
for(int j=W;j>=w[i];j--){
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
完全背包
for(int i=1;i<=n;i++)
for(int j=w[i];j<=V;j++)
f[j]=max(f[j],f[j-w[i]]+c[i]);
lower_bound(a,a+n,x)-a;
//递增三元组(lower_bound()/upper_bound()函数)
#include<stdio.h>
#include<algorithm>
#define ll long long
const int maxn=100010;
using namespace std;
int a[maxn],b[maxn],c[maxn];
ll sum=0;
int main(){
int n;scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%d",&a[i]);
for(int i=0;i<n;i++) scanf("%d",&b[i]);
for(int i=0;i<n;i++) scanf("%d",&c[i]);
sort(a,a+n);sort(b,b+n);sort(c,c+n);
for(int i=0;i<n;i++){
int x=lower_bound(a,a+n,b[i])-a;
int y=upper_bound(c,c+n,b[i])-c;
sum+=1ll*x*(n-y);
}
printf("%I64d",sum);
}
//函数lower_bound()在first和last中的前闭后开区间进行二分查找,
//返回大于或等于val的第一个元素位置。如果所有元素都小于val,则返回last的位置.
//函数upper_bound()返回的在前闭后开区间查找的关键字的上界,返回大于val的第一个元素位置
辗转相除
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll Q(ll n,ll m){
if(m==0) return n;
return Q(m,n%m);
}
int main(){
cout<<Q(15,40)<<endl;
return 0;
}
欧几里德扩展
https://www.luogu.org/problemnew/show/P1516(同余定理)
#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
ll ans,x1,y1;
ll exgcd(ll a,ll b,ll &x1, ll &y1)
{
if(!b)
{
x1=1;
y1=0;
return a;
}
ans=exgcd(b,a%b,x1,y1);
ll t=x1;
x1=y1;
y1=t-a/b*y1;
return ans;
}
int main()
{
ll n,m,x,y,l;
cin>>x>>y>>m>>n>>l;
ll b=n-m,a=x-y;
if(b<0)
{
b=-b;
a=-a;
}//处理负数
exgcd(b,l,x1,y1);
if(a%ans!=0)//判断方程有无解。
cout<<"Impossible";
else
cout<<((x1*(a/ans))%(l/ans)+(l/ans))%(l/ans);//处理负数
}
加法高精
#include<bits/stdc++.h>
using namespace std;
string a,b;
string gaoji(string a,string b){
int lena=a.length();
int lenb=b.length();
int aa,bb,sum,flag=0;
while(lena>0){
aa=a[lena-1]-'0';
if(lenb>0)
bb=b[lenb-1]-'0';
else
bb=0;
sum=aa+bb+flag;
if(sum>=10){
a[lena-1]='0'+sum%10;
flag=1;
}
else{
a[lena-1]='0'+sum;
flag=0;
}
lena--;
lenb--;
}
if(flag==1)
a="1"+a;
return a;
}
int main(){
cin>>a>>b;
if(a.size()<b.size())
swap(a,b);
cout<<gaoji(a,b)<<endl;
return 0;
}
快速幂
- 思想:
- 把10进制看作2进制,用二进制来换算10进制
- 从最低位找最高位中间的1,来成该位置的幂
#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll Q(ll n,ll m){
ll res=1;
while(m){
if(1&m)
res=res*n;
n=n*n;
m>>=1;
}
return res;
}
int main(){
for(int i=1;i<10;i++)
cout<<Q(2,i)<<endl;
return 0;
}
归并排序
//归并排序
#include<bits/stdc++.h>
using namespace std;
int a[100000];
void mergesort(int low,int high){
if(low>=high) return;
int mid=(low+high)>>1;
mergesort(low,mid);
mergesort(mid+1,high);
int *b=new int[high-low+1];
int i=low,j=mid+1,k=0;
while(i<=mid&&j<=high){
if(a[i]<a[j])
b[k++]=a[i++];
else
b[k++]=a[j++];
}
while(i<=mid) b[k++]=a[i++];
while(j<=high) b[k++]=a[j++];
for(i=low,k=0;i<=high;i++) a[i]=b[k++];
delete []b;
}
int main(){
int n;cin>>n;
for(int i=0;i<n;i++)cin>>a[i];
mergesort(0,n-1);
for(int i=0;i<n;i++) cout<<a[i]<<" ";
return 0;
}
插入排序
//定一个flag=0,a[flag]与a[flag+1]比较,满足则交换,
//交换之后,再继续交换排flag之前的数组比较 flag++;
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int a[40000];
int n,m,x,y,sum=0;
void cr(int x,int y){
if(x+1==y) return;
int flag=x;
if(a[x]>a[x+1]){
swap(a[x],a[x+1]);
for(int i=flag;i>0;i--){
if(a[i]<a[i-1])swap(a[i],a[i-1]);
}
}
cr(x+1,y);
}
int main(){
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
cr(0,n);
for(int i=0;i<n;i++) cout<<a[i]<<" ";
return 0;
}
选择排序
- 交换瓶子真题
//int k=0 在数组小标k到n中找到最小的,与a[k++]交换
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int a[40000];
int n,m,x,y,sum=0;
void xz(int a[],int begin,int end){
if(begin==end) return;
int main=a[begin],flag=begin;
for(int i=begin;i<end;i++)
if(main>a[i]){
flag=i;
main=a[i];
}
if(a[flag]!=a[begin]){
swap(a[flag],a[begin]);
sum++;
}
xz(a,begin+1,end);
}
int main(){
cin>>n;
for(int i=0;i<n;i++) cin>>a[i];
xz(a,0,n);
cout<<sum;
return 0;
}
快速排序
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int a[100];
void Q(int x,int y){
if(x>y) return;
int i=x,j=y;
while(i<j){
while(a[j]>=a[x]&&i<j)j--;
while(a[i]<=a[x]&&i<j)i++;
swap(a[i],a[j]);
}
swap(a[x],a[i]);
Q(x,i-1);
Q(i+1,y);
}
int main(){
int n;cin>>n;
for(int i=0;i<n;i++)cin>>a[i];
Q(0,n-1);
for(int i=0;i<n;i++)cout<<a[i]<<" ";
return 0;
}
优先队列
https://www.luogu.org/problemnew/show/P1090
#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
int n,x,ans;
int main(){
while(scanf("%d",&n)==1){
priority_queue<int>q;
int sum=0;
for(int i=1;i<=n;i++) {
cin>>x;
q.push(-x);
}
for(int i=1;i<n;i++){
int w=0;
w=q.top();
q.pop();
w+=q.top();
q.pop();
q.push(w);
sum+=w;
}
cout<<-1*sum<<endl;
}
return 0;
}
简单DFS遍历
- 求起点到终点要走过的的最短步数
- 障碍物用1表示,无障碍物用0表示
#include<bits/stdc++.h>
using namespace std;
int a[105][105],b[105][105];
int n,m,startx,starty,endx,endy,ans=999999999;
int next[4][2]={{1,0},{0,1},{-1,0},{0,-1}};
void dfs(int x,int y,int step){
if(x==endx&&y==endy){
ans=min(ans,step);
return;
}
for(int i=0;i<4;i++){
int xx=x+next[i][0];
int yy=y+next[i][1];
if(xx<1||xx>n||yy<1||yy>m) continue;
if(a[xx][yy]==0&&b[xx][yy]==0){
b[xx][yy]=1;
dfs(xx,yy,step+1);
b[xx][yy]=0;
}
}
return;
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
cin>>a[i][j];
cin>>startx>>starty>>endx>>endy;
dfs(startx,starty,0);
cout<<ans;
return 0;
}
最短路径(暴力)
for(int k=1;k<=n;k++){
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
if(e[i][j]>e[i][k]+e[k][j])
e[i][j]=e[i][k]+e[k][j];
}
}
}
欧拉筛
#include<iostream>
#include<string.h>
const int MAX=4e6;
using namespace std;
int prime[MAX],cnt=0;
bool vis[MAX];
void E(int n){
for(int i=2;i<=n;i++){
if(!vis[i])
prime[++cnt]=i;
for(int j=1;j<=cnt&&prime[j]*i<=n;++j){
vis[prime[j]*i]=1;
if(i%prime[j]==0)
break;
}
}
}
int main(){
int n;cin>>n;
memset(vis,0,sizeof(bool)*n);
E(n);
for(int i=1;i<=cnt;i++)
cout<<prime[i]<<endl;
}
读入优化
#include<iostream>
using namespace std;
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int n;cin>>n;cout<<n;
}
#include<stdio.h>
#include<iostream>
#include<string.h>
const int MAX=4e6;
using namespace std;
int read(){
char ch=getchar();
int x=0,f=1;
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int main(){
int x;
cout<<read();
return 0;
}
并查集
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int a[10000];
int S(int x){
if(a[x]==x) return x;
else{
a[x]=S(a[x]);
return a[x];
}
}
void B(int x,int y){
int xx=S(x);
int yy=S(y);
if(xx!=yy)
a[yy]=xx;
}
int main(){
int n,sum=0;cin>>n;
for(int i=1;i<=n;i++)a[i]=i;
for(int i=1;i<=n;i++){
int x,y;cin>>x>>y;
B(x,y);
}
for(int i=1;i<=n;i++)
if(a[i]==i)
sum++;
cout<<sum;
return 0;
}
阶乘高精
#include<bits/stdc++.h>
using namespace std;
int num[5000];
int gaojing(int num[],int n){
int len=1;
num[0]=1;
for(int i=1;i<=n;i++){
len=0;
int p=0;
int jw=0;
while(num[p]!=-1){
num[p]*=i;
num[p]+=jw;
jw=0;
if(num[p]>=10){
jw=num[p]/10;
num[p]%=10;
}
p++;
len++;
}
if(jw!=0){
while(jw){
num[p++]=jw%10;
jw/=10;
len++;
}
}
}
return len-1;
}
int main(){
int n;
while(cin>>n){
memset(num,-1,sizeof(num));
int len=gaojing(num,n);
for(len;len>=0;len--){
cout<<num[len];
}
cout<<endl;
}
return 0;
}
vector
#include<bits/stdc++.h>
using namespace std;
vector<int> a[100];
int main(){
//输入
a[10].push_back(50);
a[10].push_back(10);
a[10].push_back(100);
//排序
sort(a[10].begin(),a[10].begin()+3);
//大小
cout<<a[10].size()<<endl;
//输出
for(vector<int>::iterator it=a[10].begin();it!=a[10].end();it++){
cout<<*it<<" ";
}
cout<<endl;
//删除最后一个元素;
a[10].pop_back();
//输出元素
for(int i=0;i<a[10].size();i++)
cout<<a[10][i]<<" ";
return 0;
}
set
#include<iostream>
#include<set>
using namespace std;
int main(){
set<int> s;
s.insert(1);
s.insert(5);
s.insert(7);
s.erase(1);//删除元素
for(set<int>::iterator it=s.begin();it!=s.end();it++){
cout<<*it<<endl;
}
return 0;
}
map
#include<iostream>
#include<map>
using namespace std;
int main(){
map<string,int>mmp;
int n;cin>>n;
for(int i=1;i<=n;i++){
string s;
cin>>s;
mmp[s]++;
}
for(map<string,int>::iterator it=mmp.begin();it!=mmp.end();it++){
cout<<it->first<<" "<<it->second<<endl;
}
return 0;
}
数组长度
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
char a[1000];
int b[]={1,2,3,4,5,6,7,8,9};
int n;
int main(){
gets(a);
puts(a);
cout<<sizeof(a)/sizeof(a[0])<<endl;
cout<<strlen(a)<<endl;
cout<<sizeof(b)/sizeof(int);
return 0;
}
运算
- &:两个都为1才为1;
- | :一个为1都为1;
- ^:相反为1,其余为0;
sort:字符数字串字典序
#include<bits/stdc++.h>
using namespace std;
//algorithm
string a[21];
bool cmp(string a,string b){
return a+b > b+a;//a+b就是字符串的连接,******数字字符串是可以直接比较大小的
}
int main(){
int n;cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++)cout<<a[i]<<" ";
return 0;
}
substr(string)
#include<iostream>
using namespace std;
int main(){
string s;cin>>s;
cout<<s.substr(0)<<endl<<s.substr(1)<<endl<<s.substr(0,5)<<endl;
return 0;
}
sstream 和 atoi
- 将字符串类型中的最前面数字转换为整数类型
#include<iostream>
#include<sstream>
using namespace std;
int main(){
int x;string s;
cin>>s;
stringstream ss(s);
ss>>x;
cout<<x;
return 0;
}
#include<iostream>
#include<sstream>
#include<cstdlib>
using namespace std;
int main(){
int x;string s;
cin>>s;
x=atoi(s.c_str());
cout<<x;
return 0;
}
next_permutation()全排列函数
- 蓝桥杯好多题都用到了全排列
#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
int main(){
string s="1234567";int sum=0;
do{
cout<<s<<'\n';
sum++;
}while(next_permutation(s.begin(),s.end()));
cout<<sum<<'\n';
return 0;
}