A + B 题解
好久都没上OJ 刷题了,今天先发个题解。
第一次嘛,自然是A+B Problem 喽
题目描述
输入两个整数a,b,输出它们的和(|a|,|b|<=10^9)。
输入输出格式
输入格式:
两个整数以空格分开
输出格式:
一个数
输入输出样例
输入样例#1:
0 1
输出样例#1:
1
说明
在OI 中,C/C++的main函数必须是int类型,而且最后要return 0。
下面是来源于洛谷的两句话:
好吧,同志们,我们就从这一题开始,向着大牛的路进发。
“任何一个伟大的思想,都有一个微不足道的开始。”
算法
大部分来自洛谷,日后自己重写,如有侵权,下方留言
luogu正常人类做法
非常人类做法
LCT
#include<iostream> #include<cstring> #include<cstdio> #include<cstring> using namespace std; struct node { int data,rev,sum; node *son[2],*pre; bool judge(); bool isroot(); void pushdown(); void update(); void setson(node *child,int lr); }lct[233]; int top,a,b; node *getnew(int x) { node *now=lct+ ++top; now->data=x; now->pre=now->son[1]=now->son[0]=lct; now->sum=0; now->rev=0; return now; } bool node::judge(){return pre->son[1]==this;} bool node::isroot() { if(pre==lct)return true; return !(pre->son[1]==this||pre->son[0]==this); } void node::pushdown() { if(this==lct||!rev)return; swap(son[0],son[1]); son[0]->rev^=1; son[1]->rev^=1; rev=0; } void node::update(){sum=son[1]->sum+son[0]->sum+data;} void node::setson(node *child,int lr) { this->pushdown(); child->pre=this; son[lr]=child; this->update(); } void rotate(node *now) { node *father=now->pre,*grandfa=father->pre; if(!father->isroot()) grandfa->pushdown(); father->pushdown();now->pushdown(); int lr=now->judge(); father->setson(now->son[lr^1],lr); if(father->isroot()) now->pre=grandfa; else grandfa->setson(now,father->judge()); now->setson(father,lr^1); father->update();now->update(); if(grandfa!=lct) grandfa->update(); } void splay(node *now) { if(now->isroot())return; for(;!now->isroot();rotate(now)) if(!now->pre->isroot()) now->judge()==now->pre->judge()?rotate(now->pre):rotate(now); } node *access(node *now) { node *last=lct; for(;now!=lct;last=now,now=now->pre) { splay(now); now->setson(last,1); } return last; } void changeroot(node *now) { access(now)->rev^=1; splay(now); } void connect(node *x,node *y) { changeroot(x); x->pre=y; access(x); } void cut(node *x,node *y) { changeroot(x); access(y); splay(x); x->pushdown(); x->son[1]=y->pre=lct; x->update(); } int query(node *x,node *y) { changeroot(x); node *now=access(y); return now->sum; } int main() { scanf("%d%d",&a,&b); node *A=getnew(a); node *B=getnew(b); //连边 Link connect(A,B); //断边 Cut cut(A,B); //再连边orz Link again connect(A,B); printf("%d\n",query(A,B)); return 0; }
Splay
//一颗资瓷区间加、区间翻转、区间求和的Splay #include <bits/stdc++.h> #define ll long long #define N 100000 using namespace std; int sz[N], rev[N], tag[N], sum[N], ch[N][2], fa[N], val[N]; int n, m, rt, x; void push_up(int x){ sz[x] = sz[ch[x][0]] + sz[ch[x][1]] + 1; sum[x] = sum[ch[x][1]] + sum[ch[x][0]] + val[x]; } void push_down(int x){ if(rev[x]){ swap(ch[x][0], ch[x][1]); if(ch[x][1]) rev[ch[x][1]] ^= 1; if(ch[x][0]) rev[ch[x][0]] ^= 1; rev[x] = 0; } if(tag[x]){ if(ch[x][1]) tag[ch[x][1]] += tag[x], sum[ch[x][1]] += tag[x]; if(ch[x][0]) tag[ch[x][0]] += tag[x], sum[ch[x][0]] += tag[x]; tag[x] = 0; } } void rotate(int x, int &k){ int y = fa[x], z = fa[fa[x]]; int kind = ch[y][1] == x; if(y == k) k = x; else ch[z][ch[z][1]==y] = x; fa[x] = z; fa[y] = x; fa[ch[x][!kind]] = y; ch[y][kind] = ch[x][!kind]; ch[x][!kind] = y; push_up(y); push_up(x); } void splay(int x, int &k){ while(x != k){ int y = fa[x], z = fa[fa[x]]; if(y != k) if(ch[y][1] == x ^ ch[z][1] == y) rotate(x, k); else rotate(y, k); rotate(x, k); } } int kth(int x, int k){ push_down(x); int r = sz[ch[x][0]]+1; if(k == r) return x; if(k < r) return kth(ch[x][0], k); else return kth(ch[x][1], k-r); } void split(int l, int r){ int x = kth(rt, l), y = kth(rt, r+2); splay(x, rt); splay(y, ch[rt][1]); } void rever(int l, int r){ split(l, r); rev[ch[ch[rt][1]][0]] ^= 1; } void add(int l, int r, int v){ split(l, r); tag[ch[ch[rt][1]][0]] += v; val[ch[ch[rt][1]][0]] += v; push_up(ch[ch[rt][1]][0]); } int build(int l, int r, int f){ if(l > r) return 0; if(l == r){ fa[l] = f; sz[l] = 1; return l; } int mid = l + r >> 1; ch[mid][0] = build(l, mid-1, mid); ch[mid][1] = build(mid+1, r, mid); fa[mid] = f; push_up(mid); return mid; } int asksum(int l, int r){ split(l, r); return sum[ch[ch[rt][1]][0]]; } int main(){ //总共两个数 n = 2; rt = build(1, n+2, 0);//建树 for(int i = 1; i <= n; i++){ scanf("%d", &x); add(i, i, x);//区间加 } rever(1, n);//区间翻转 printf("%d\n", asksum(1, n));//区间求和 return 0; }
Floyd
#include <cstdio> const int N=5,oo=1023741823; int f[N][N]; inline int mn(int a,int b){ return a<b?a:b; } void floyd() {//floyd模板 for (int k=1; k<=N; k++) for (int i=1; i<=N; i++) if (i==k) continue; else for (int j=1; j<=N; j++) if (k==j||i==j) continue; else f[i][j]=mn(f[i][j],f[i][k]+f[k][j]); } int main(){ int a,b; for (int i=1;i<=N;i++) for (int j=1;j<=N;j++) f[i][j]=oo; scanf ("%d %d",&a,&b); f[1][2]=a; f[2][3]=b;//构图,1->2的最短路径是a,2->3的最短路径是b,那么1->3的最短路就是a+b floyd(); printf ("%d",f[1][3]);//输出 return 0; }
二分法
#include<cstdio> using namespace std; int a,b,c; int main(){long long l=-int(1e9)<<1,r=int(1e9)<<1;//左边界和右边界 scanf("%d%d",&a,&b); while(r-l>1){c=(l+r)>>1;//二分的步骤啦 if(c-b<a)l=c; else if(c-b>a)r=c; else return printf("%d\n",c),0; }if(l!=r)return printf("%d\n",r),0; }
树状数组
#include<iostream> #include<cstring> using namespace std; int lowbit(int a) { return a&(-a); } int main() { int n=2,m=1; int ans[m+1]; int a[n+1],c[n+1],s[n+1]; int o=0; memset(c,0,sizeof(c)); s[0]=0; for(int i=1;i<=n;i++) { cin>>a[i]; s[i]=s[i-1]+a[i]; c[i]=s[i]-s[i-lowbit(i)];//树状数组创建前缀和优化 } for(int i=1;i<=m;i++) { int q=2; //if(q==1) //{(没有更改操作) // int x,y; // cin>>x>>y; // int j=x; // while(j<=n) // { // c[j]+=y; // j+=lowbit(j); // } //} //else { int x=1,y=2;//求a[1]+a[2]的和 int s1=0,s2=0,p=x-1; while(p>0) { s1+=c[p]; p-=lowbit(p);//树状数组求和操作,用两个前缀和相减得到区间和 } p=y; while(p>0) { s2+=c[p]; p-=lowbit(p); } o++; ans[o]=s2-s1;//存储答案 } } for(int i=1;i<=o;i++) cout<<ans[i]<<endl;//输出 return 0; }
二进制
#include<iostream> #include<cstdio> #include<cstdlib> #include<cmath> #include<algorithm> using namespace std; int main() { int a,b,s=0,s1=0,i=0,na=0,nb=0; cin>>a>>b; if(a<=0) na=1,a*=-1; while(a!=0) { if(a%2!=0) s+=pow(2,a%2*i); a/=2; i++; } i=0; if(na==1) s*=-1; if(b<=0) nb=1,b*=-1; while(b!=0) { if(b%2!=0) s1+=pow(2,b%2*i); b/=2; i++; } if(nb==1) s1*=-1; cout<<s+s1;; return 0; }
SPFA
#include<cstdio> using namespace std; int n,m,a,b,op,head[200009],next[200009],dis[200009],len[200009],v[200009],l,r,team[200009],pd[100009],u,v1,e; int lt(int x,int y,int z) { op++,v[op]=y; next[op]=head[x],head[x]=op,len[op]=z; } int SPFA(int s,int f)//SPFA…… { for(int i=1;i<=200009;i++){dis[i]=999999999;} l=0,r=1,team[1]=s,pd[s]=1,dis[s]=0; while(l!=r) { l=(l+1)%90000,u=team[l],pd[u]=0,e=head[u]; while(e!=0) { v1=v[e]; if(dis[v1]>dis[u]+len[e]) { dis[v1]=dis[u]+len[e]; if(!pd[v1]) { r=(r+1)%90000, team[r]=v1, pd[v1]=1; } } e=next[e]; } } return dis[f]; } int main() { scanf("%d%d",&a,&b); lt(1,2,a);lt(2,3,b);//1到2为a,2到3为b,1到3即为a+b…… printf("%d",SPFA(1,3)); return 0; }
递归
#include<iostream> using namespace std; long long a,b,c; long long dg(long long a) { if(a<=5){return a;}//防超时…… return (dg(a/2)+dg(a-a/2)); } int main() { cin>>a>>b; c=dg(a)+dg(b); cout<<c; }
高精
#include<iostream> #include<cstring> using namespace std; int main() { char a1[1000],b1[1000]; int a[1000]={0},b[1000]={0},c[1000]={0},la,lb,lc,i,x; cin>>a1>>b1; la=strlen(a1); lb=strlen(b1); for(i=0;i<=la-1;i++){a[la-i]=a1[i]-48;} for(i=0;i<=lb-1;i++){b[lb-i]=b1[i]-48;} lc=1,x=0; while(lc<=la||lc<=lb){c[lc]=a[lc]+b[lc]+x,x=c[lc]/10,c[lc]%=10,lc++;} c[lc]=x; if(c[lc]==0){lc--;} for(i=lc;i>=1;i--){cout<<c[i];} cout<<endl; return 0;
压位高精
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #define p 8 #define carry 100000000 using namespace std; const int Maxn=50001; char s1[Maxn],s2[Maxn]; int a[Maxn],b[Maxn],ans[Maxn]; int change(char s[],int n[]) { char temp[Maxn]; int len=strlen(s+1),cur=0; while(len/p) { strncpy(temp,s+len-p+1,p); n[++cur]=atoi(temp); len-=p; } if(len) { memset(temp,0,sizeof(temp)); strncpy(temp,s+1,len); n[++cur]=atoi(temp); } return cur; } int add(int a[],int b[],int c[],int l1,int l2) { int x=0,l3=max(l1,l2); for(int i=1;i<=l3;i++) { c[i]=a[i]+b[i]+x; x=c[i]/carry; c[i]%=carry; } while(x>0){c[++l3]=x%10;x/=10;} return l3; } void print(int a[],int len) { printf("%d",a[len]); for(int i=len-1;i>=1;i--)printf("%0*d",p,a[i]); printf("\n"); } int main() { scanf("%s%s",s1+1,s2+1); int la=change(s1,a); int lb=change(s2,b); int len=add(a,b,ans,la,lb); print(ans,len); }
读入输出优化
#include <cstdio> const size_t fSize = 1 << 15; char iFile[fSize], *iP = iFile, oFile[fSize], *oP = oFile; inline char readchar() { if (*iP && iP - iFile < fSize) { char t = *iP; iP++; return t; } else return EOF; } template<typename T> inline void readint(T &x) { x = 0; char c; bool neg = 0; while ((c = readchar()) < '0' || c > '9') if (c == '-') neg = !neg; while (c >= '0' && c <= '9') x = x * 10 + (c ^ 48), c = readchar(); x = neg ? -x : x; } inline void writechar(const char &c) { *oP = c, ++oP; } template<typename T> inline void _writeint(const T &x) { if (!x) return; _writeint(x / 10); writechar(x % 10 ^ 48); } template<typename T> inline void writeint(T x, const char &c) { if (x < 0) { writechar('-'); x = -x; } if (!x) { writechar('0'); return; } _writeint(x); writechar(c); } int main() { fread(iFile, 1, fSize, stdin); int a, b; readint(a); readint(b); writeint(a + b, '\n'); fwrite(oFile, 1, oP - oFile, stdout); return 0; }
位运算非递归
#include <cstdio> int m, n; int main() { scanf("%d%d", &m, &n); int u = m & n; int v = m ^ n; while (u) { int s = v; int t = u << 1; u = s & t; v = s ^ t; } printf("%d\n", v); }
LCA
#include<cstdio> //头文件 #define NI 2 //从来不喜欢算log所以一般用常数 不知道算不算坏习惯 因为3个节点 所以log3(当然以2为底)上取整得2 struct edge { int to,next,data; //分别表示边的终点,下一条边的编号和边的权值 }e[30]; //邻接表,点少边少开30是为了浪啊 int v[10],d[10],lca[10][NI+1],f[10][NI+1],tot=0; //数组开到10依然为了浪 //数组还解释嘛,v表示第一条边在邻接表中的编号,d是深度,lca[x][i]表示x向上跳2^i的节点,f[x][i]表示x向上跳2^i的距离和 void build(int x,int y,int z) //建边 { e[++tot].to=y; e[tot].data=z; e[tot].next=v[x]; v[x]=tot; e[++tot].to=x; e[tot].data=z; e[tot].next=v[y]; v[y]=tot; } void dfs(int x) //递归建树 { for(int i=1;i<=NI;i++) //懒,所以常数懒得优化 f[x][i]=f[x][i-1]+f[lca[x][i-1]][i-1], lca[x][i]=lca[lca[x][i-1]][i-1]; //建树的同时进行预处理 for(int i=v[x];i;i=e[i].next) //遍历每个连接的点 { int y=e[i].to; if(lca[x][0]==y) continue; lca[y][0]=x; //小技巧:lca[x][0]即为x的父亲~~(向上跳2^0=1不就是父节点嘛) f[y][0]=e[i].data; d[y]=d[x]+1; dfs(y); //再以这个节点为根建子树【这里真的用得到嘛??】 } } int ask(int x,int y) //询问,也是关键 { if(d[x]<d[y]) {int t=x;x=y;y=t;} //把x搞成深的点 int k=d[x]-d[y],ans=0; for(int i=0;i<=NI;i++) if(k&(1<<i)) //若能跳就把x跳一跳 ans+=f[x][i], //更新信息 x=lca[x][i]; for(int i=NI;i>=0;i--) //不知道能不能正着循环,好像倒着优,反正记得倒着就好了 if(lca[x][i]!=lca[y][i]) //如果x跳2^i和y跳2^j没跳到一起就让他们跳 ans+=f[x][i]+f[y][i], x=lca[x][i],y=lca[y][i]; return ans+f[x][0]+f[y][0]; //跳到LCA上去(每步跳的时候都要更新信息,而且要在跳之前更新信息哦~) } int main() { int a,b; scanf("%d%d",&a,&b); build(1,2,a); build(1,3,b); //分别建1 2、1 3之间的边 dfs(1); //以1为根建树 printf("%d",ask(2,3)); //求解2 3到它们的LCA的距离和并输出 }
字典树
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; struct node{ int str[26]; int sum; }s[1000]; char str1[100]; int t=0,tot=0,ss=0; bool f1; void built() { t=0; for(int i=0;i<strlen(str1);i++) { if(str1[i]=='-'){ f1=true;continue; } if(!s[t].str[str1[i]-'0']) s[t].str[str1[i]-'0']=++tot; t=s[t].str[str1[i]-'0']; s[t].sum=str1[i]-'0'; } } int query() { int t=0;int s1=0; for(int i=0;i<strlen(str1);i++) { if(str1[i]=='-') continue; if(!s[t].str[str1[i]-'0']) return s1; t=s[t].str[str1[i]-'0']; s1=s1*10+s[t].sum; } return s1; } int main() { for(int i=1;i<=2;i++) { f1=false; scanf("%s",str1); built(); if(f1) ss-=query(); else ss+=query(); } printf("%d",ss); return 0; }
模拟
#include <iostream> #include <cmath> using namespace std; int fu=1,f=1,a,b,c=0; int main() { cin>>a>>b; if(a<0&&b>0)fu=2; if(a>0&&b<0)fu=3; if(a<0&&b<0)f=-1; if(a==0){cout<<b;return 0;} if(b==0){cout<<a;return 0;} a=abs(a); b=abs(b); if(a>b&&fu==3)f=1; if(b>a&&fu==3)f=-1; if(b>a&&fu==2)f=1; if(b<a&&fu==2)f=-1; if(fu==1)c=a+b; if(fu>1)c=max(a,b)-min(a,b); c*=f; cout<<c; return 0; }
位运算非递归
#include <iostream> using namespace std; int plus(int a,int b)//这个是加法运算函数 { if(b==0)//如果b(进位)是0(没有进位了),返回a的值 return a; else { int xor,carry; xor=a^b;//xor是a和b不进位加法的值 carry=(a&b)<<1;//carry是a和b进位的值(只有两个都是1才会产生进位,所以是与运算。左移一位是因为二进制加法和十进制加法竖式一样进位要加在左面一位里) return plus(xor,carry);//把不进位加法和进位的值的和就是结果 } } int main() { int a,b; cin >> a >> b; cout << plus(a,b) << endl; return 0; }
线段树
#include<cstdio> #include<algorithm> #include<cstdlib> #include<cmath> #include<cstring> #include<iostream> using namespace std; struct node{ int val,l,r; }; node t[5]; int a[5],f[5]; int n,m; void init(){ for(int i=1;i<=2;i++){ scanf("%d",&a[i]); } } void build(int l,int r,int node){//这是棵树 t[node].l=l;t[node].r=r;t[node].val=0; if(l==r){ f[l]=node; t[node].val=a[l]; return; } int mid=(l+r)>>1; build(l,mid,node*2); build(mid+1,r,node*2+1); t[node].val=t[node*2].val+t[node*2+1].val; } void update(int node){ if(node==1)return; int fa=node>>1; t[fa].val=t[fa*2].val+t[fa*2+1].val; update(fa); } int find(int l,int r,int node){ if(t[node].l==l&&t[node].r==r){ return t[node].val; } int sum=0; int lc=node*2;int rc=lc+1; if(t[lc].r>=l){ if(t[lc].r>=r){ sum+=find(l,r,lc); } else{ sum+=find(l,t[lc].r,lc); } } if(t[rc].l<=r){ if(t[rc].l<=l){ sum+=find(l,r,rc); } else{ sum+=find(t[rc].l,r,rc); } } return sum; } int main(){ init(); build(1,2,1); printf("%d",find(1,2,1)); }
Dijkstra
#include <iostream> #include <cstdio> #include <cstdlib> #include <cmath> #include <cctype> #include <climits> #include <algorithm> #include <map> #include <queue> #include <vector> #include <ctime> #include <string> #include <cstring> using namespace std; const int N=405; struct Edge { int v,w; }; vector<Edge> edge[N*N]; int n; int dis[N*N]; bool vis[N*N]; struct cmp { bool operator()(int a,int b) { return dis[a]>dis[b]; } }; int Dijkstra(int start,int end) { priority_queue<int,vector<int>,cmp> dijQue; memset(dis,-1,sizeof(dis)); memset(vis,0,sizeof(vis)); dijQue.push(start); dis[start]=0; while(!dijQue.empty()) { int u=dijQue.top(); dijQue.pop(); vis[u]=0; if(u==end) break; for(int i=0; i<edge[u].size(); i++) { int v=edge[u][i].v; if(dis[v]==-1 || dis[v]>dis[u]+edge[u][i].w) { dis[v]=dis[u]+edge[u][i].w; if(!vis[v]) { vis[v]=true; dijQue.push(v); } } } } return dis[end]; } int main() { int a,b; scanf("%d%d",&a,&b); Edge Qpush; Qpush.v=1; Qpush.w=a; edge[0].push_back(Qpush); Qpush.v=2; Qpush.w=b; edge[1].push_back(Qpush); printf("%d",Dijkstra(0,2)); return 0; }
最小生成树
#include <cstdio> #include <algorithm> #define INF 2140000000 using namespace std; struct tree{int x,y,t;}a[10]; bool cmp(const tree&a,const tree&b){return a.t<b.t;} int f[11],i,j,k,n,m,x,y,t,ans; int root(int x){if (f[x]==x) return x;f[x]=root(f[x]);return f[x];} int main(){ for (i=1;i<=10;i++) f[i]=i; for (i=1;i<=2;i++){ scanf("%d",&a[i].t); a[i].x=i+1;a[i].y=1;k++; } a[++k].x=1;a[k].y=3,a[k].t=INF; sort(a+1,a+1+k,cmp); for (i=1;i<=k;i++){ // printf("%d %d %d %d\n",k,a[i].x,a[i].y,a[i].t); x=root(a[i].x);y=root(a[i].y); if (x!=y) f[x]=y,ans+=a[i].t; } printf("%d\n",ans); }
标程
大部分来自洛谷,日后自己重写,如有侵权,下方留言
luoguC++
#include <iostream> int main(int argc, char const *argv[]) { long long a, b; std::cin >> a >> b; std::cout << a + b << std::endl; return 0; }
C
#include <stdio.h> int main(int argc, char const *argv[]) { long long a, b; scanf("%lld%lld", &a, &b); printf("%lld", a + b); return 0; }
Pascal
var a, b: longint; begin readln(a,b); writeln(a+b); end.
Python3
s = input().split() print(int(s[0]) + int(s[1]))
Java
import java.io.*; import java.util.*; public class Main { public static void main(String args[]) throws Exception { Scanner cin=new Scanner(System.in); int a = cin.nextInt(), b = cin.nextInt(); System.out.println(a+b); } }
JavaScript (Node.js)
const fs = require('fs'); const data = fs.readFileSync('/dev/stdin'); const result = data.toString('ascii').trim().split(' ').map(function(x) { return parseInt(x); }).reduce(function(a, b) { return a + b; }, 0); console.log(result);
一道题满足各个算法标签。
我说你的球怎么这么快就那么大。
当初看A+B Problem 题解时是懵逼的,现在看看,唉,怪自己太弱了
加油吧。