資料結構
莫隊
普通莫隊
題目來源:P1494 [國家集訓隊] 小 Z 的襪子。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 10;
struct node
{
int l, r, id;
} q[N];
struct node2
{
int c, s;
} ans[N];
int n, m;
int a[N], st[N], ed[N], vis[N], be[N];
int sum;
bool cmp(node x, node y)
{
if (be[x.l] == be[y.l])
return be[x.r] == be[x.r] ? (x.r < y.r) : (be[x.r] < be[y.r]);
return be[x.l] < be[y.l];
}
void ins(int x)
{
sum += (2 * vis[a[x]]);
vis[a[x]]++;
}
void de(int x)
{
sum = sum - 2 * vis[a[x]] + 2;
vis[a[x]]--;
}
long long gcdd(long long a, long long b)
{
return b != 0 ? gcdd(b, a % b) : a;
}
signed main()
{
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i];
for (int i = 1; i <= m; i++)
cin >> q[i].l >> q[i].r, q[i].id = i;
int t = sqrt(m);
for (int i = 1; i <= t; i++)
st[i] = (i - 1) * t + 1, ed[i] = i * t;
if (m > ed[t])
t++, st[t] = ed[t - 1] + 1, ed[t] = n;
for (int i = 1; i <= t; i++)
for (int j = st[i]; j <= ed[i]; j++)
be[j] = i;
sort(q + 1, q + 1 + m, cmp);
int l = 1, r = 0;
for (int i = 1; i <= m; i++)
{
if (q[i].l == q[i].r)
{
ans[q[i].id] = {1, 0};
continue;
}
while (l > q[i].l)
ins(--l);
while (r < q[i].r)
ins(++r);
while (l < q[i].l)
de(l++);
while (r > q[i].r)
de(r--);
long long x = (r - l + 1) * (r - l);
long long y = sum;
long long z = gcdd(x, sum);
ans[q[i].id].c = x / z;
ans[q[i].id].s = y / z;
}
for (int i = 1; i <= m; i++)
{
printf("%d/%d\n", ans[i].s, ans[i].c);
}
return 0;
}
樹上莫隊
問題求解樹上兩個節點 \(u,v\) 最短路徑上節點的權值中位數。
演算法:莫隊加分塊。
把樹變成括號序,記錄 \(dfn[i]\),\(id[0][i],id[1][i]\),表示括號序,括號序的對映。
詢問分兩種情況:
先保持:\(id[1][u]<=id[1][v]\),為了使 \(u\) 在 \(v\) 前面。
-
\(u,v\) 在兩個子樹內,\(q[i]={id[1][u],id[0][v],i}\),先上去(從 \(u\) 回溯開始)再下去(到 \(v\) 搜尋開始)。
-
\(u,v\) 在一個子樹內,\(q[i]={id[0][v]+1,id[0][u],i}\),\(u\) 在 \(v\) 中,從 \(v\) 走到 \(u\)。
莫隊移動 \(l,r\) 時,如果 \(u\) 在不在 \(l,r\) 中,就執行原來的操作,如果不在就執行相反的。
void upd(int u,int op)
{
(usd[u]&1)?del(u):ins(u);
usd[u]+=op?1:-1;
}
code:
#include<bits/stdc++.h>
#define pii pair<int,int>
using namespace std;
const int N=2e5+10;
int las[N],to[N],nxt[N],cnt,c[N],id[2][N],a[N];
int dfn[N],tot,col[N],usd[N],ss;
double ans[N];
int n,mm,maxx;
struct node2
{
int l,r,id;
}q[N];
struct node
{
int l[N],r[N],sum[N],len,m,be[N],B;
void clear()
{
memset(sum,0,sizeof sum);
}
void init()
{
B=sqrt(len);
m=len/B;
for(int i=1;i<=m;i++)
l[i]=(i-1)*B+1,r[i]=i*B;
if(r[m]<len)
l[m+1]=r[m]+1,r[++m]=len;
for(int i=1;i<=m;i++)
for(int j=l[i];j<=r[i];j++) be[j]=i;
}
}t,mid;
void add(int u,int v,int w)
{
nxt[++cnt]=las[u];
las[u]=cnt;
to[cnt]=v;
c[cnt]=w;
}
bool cmp(node2 a,node2 b)
{
int la=a.l,lb=b.l,ra=a.r,rb=b.r;
if(t.be[la]!=t.be[lb])return t.be[la]<t.be[lb];
return ra<rb;
}
void dfs(int u,int fa)
{
dfn[++tot]=u;
id[0][u]=tot;
for(int e=las[u];e;e=nxt[e])
{
int v=to[e];
if(v==fa) continue;
a[v]=c[e];
dfs(v,u);
}
dfn[++tot]=u;
id[1][u]=tot;
}
void ins(int x)
{
x=a[x];
col[x]++;
mid.sum[mid.be[x]]++;
ss++;
}
void del(int x)
{
x=a[x];
col[x]--;
mid.sum[mid.be[x]]--;
ss--;
}
void upd(int u,int op)
{
(usd[u]&1)?del(u):ins(u);
usd[u]+=op?1:-1;
}
int get(int x)
{
int now=0;
for(int i=1;i<=mid.m;i++)
if(mid.sum[i]+now>=x)
{
for(int j=mid.l[i];j<=mid.r[i];j++)
if(now+col[j]>=x) return j;
else now+=col[j];
}
else now+=mid.sum[i];
}
void sovle()
{
memset(las,0,sizeof las);
memset(col,0,sizeof col);
memset(usd,0,sizeof usd);
t.clear(),mid.clear();
cnt=ss=tot=0;
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w),add(v,u,w);
maxx=max(maxx,w);
}
dfs(1,0);
t.len=tot,mid.len=maxx;
t.init(),mid.init();
scanf("%d",&mm);
for(int i=1;i<=mm;i++)
{
int u,v;
scanf("%d%d",&u,&v);
if(id[1][u]>id[1][v]) swap(u,v);
if(id[0][u]<id[0][v]) q[i]={id[1][u],id[0][v],i};
else q[i]={id[0][v]+1,id[0][u],i};
}
sort(q+1,q+1+mm,cmp);
int l=1,r=0;
for(int i=1;i<=mm;i++)
{
//cout<<q[i].l<<" "<<q[i].r<<endl;
while(l>q[i].l) upd(dfn[--l],1);
while(r<q[i].r) upd(dfn[++r],1);
while(l<q[i].l) upd(dfn[l++],0);
while(r>q[i].r) upd(dfn[r--],0);
//cout<<ss<<endl;
//for(int i=1;i<=maxx;i++) cout<<col[i]<<" "; cout<<endl;
ans[q[i].id]=ss&1?get((ss+1)/2):(get(ss/2+1)+get(ss/2))/2.0;
//cout<<"ans"<<ans[q[i].id]<<endl;
}
for(int i=1;i<=mm;i++) printf("%.1lf\n",ans[i]);
}
int main()
{
int T;
scanf("%d",&T);
while(T--) sovle();
return 0;
}
/*
多測的資料
2
6
1 2 9
2 5 5
2 4 7
3 5 1
3 6 4
3
1 3
4 6
2 6
6
1 2 9
2 5 5
2 4 7
3 5 1
3 6 4
3
1 3
4 6
2 6
*/
圖論
樹的基本知識
樹的重心
沒有模板題,用的會議這道題。
#include<bits/stdc++.h>
using namespace std;
const int N=5e4+10;
vector<int>e[N];
int n;
int siz[N],res,d[N],f[N];
void dfs(int u,int fa)
{
siz[u]=1;
mx=0;
for(auto v : e[u])
{
if(v==fa) continue;
dfs(v,u);
siz[u]+=siz[v];
f[u]=max(siz[v],f[u]);
}
f[u]=max(n-siz[u],f[u]);
if(f[u]<f[res]||(f[u]==f[res]&&res>u))
res=u;
}
void dfs2(int u,int fa)
{
for(auto v : e[u])
{
if(v==fa) continue;
d[v]=d[u]+1;
dfs2(v,u);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
f[0]=1e9+10;
dfs(1,0);
dfs2(res,0);
for(int i=1;i<=n;i++)
ans+=d[i];
printf("%d %d",res,ans);
}
重鏈剖分
兩次搜尋預處理。
void dfs1(int u,int fa)
{
f[u]=fa;
siz[u]=1;
dep[u]=dep[fa]+1;
for(int e=las[u];e;e=nxt[e])
{
int v=to[e];
dfs1(v,u);
siz[u]+=siz[v];
if(siz[son[u]]<siz[v]) son[u]=v;
}
}
void dfs2(int u,int tp_now)
{
id[0][u]=++tim;
dfn[tim]=u;
tp[u]=tp_now;
if(son[u])
dfs2(son[u],tp_now);
for(int e=las[u];e;e=nxt[e])
{
int v=to[e];
if(son[u]==v||v==f[u]) continue;
dfs2(v,v);
}
id[1][u]=tim;
}
線段樹區間操作時的跳鏈:
void upchange(int u,int v,int x)
{
// cout<<"#####"<<endl;
while(top[u]!=top[v])
{
if(dep[tp[u]]<dep[tp[v]])swap(u,v);
change(1, id[0][tp[u]], id[0][u], x);
u=f[tp[u]];
}
if(dep[u]>dep[v])swap(u,v);
change(1, id[0][u], id[0][v], x);
}
int upask(int u,int v)
{
int res=0;
while(tp[u]!=tp[v])
{
if(dep[tp[u]]<dep[tp[v]])swap(u,v);
res+=ask(1, id[0][tp[u]], id[0][u]);
res%=mod;
u=f[tp[u]];
}
if(dep[u]>dep[v])swap(u,v);
res+=ask(1, id[0][u], id[0][v]);
return res%mod;
}
最短路
Floyd
#include <bits/stdc++.h>
using namespace std;
const int N = 500 + 10, inf = 1e9 + 10;
int n, m;
int dis[N][N];
int main()
{
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
if (i != j)
dis[i][j] = inf;
for (int i = 1; i <= m; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
dis[u][v] = dis[v][u] = min(dis[u][v], w);
}
for (int k = 1; k <= n; k++)
for (int i = 1; i <= n; i++)
for (int j = 1; j <= n; j++)
dis[i][j] = min(dis[i][k] + dis[k][j], dis[i][j]);
for (int i = 1; i <= n; i++)
{
for (int j = 1; j <= n; j++)
printf("%d ", dis[i][j]);
puts("");
}
return 0;
}
dijstra
#include <bits/stdc++.h>
#define pii pair<long long, int>
typedef long long ll;
using namespace std;
const int N = 2e5 + 10;
int n, m, s;
ll dis[N];
bool vis[N];
vector<pii> e[N];
int main()
{
scanf("%d%d%d", &n, &m, &s);
for (int i = 1; i <= m; i++)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
e[u].push_back({v, w});
e[v].push_back({u, w});
}
priority_queue<pii, vector<pii>, greater<pii>> q;
memset(dis, 0x3f, sizeof dis);
dis[s] = 0;
q.push({0, s});
while (!q.empty())
{
int u = q.top().second;
q.pop();
if (vis[u])
continue;
vis[u] = 1;
for (auto t : e[u])
{
int v = t.first, w = t.second;
if (dis[v] > dis[u] + w)
dis[v] = dis[u] + w, q.push({dis[v], v});
}
}
for (int i = 1; i <= n; i++)
printf("%lld ", dis[i]);
return 0;
}
johnson
#include<bits/stdc++.h>
#define pii pair<int,int>
typedef long long ll;
using namespace std;
const int N=3e3+10,M=6e3+10;
const ll inf=1e18;
int n,m,num[N];
vector<pii>e[N];
ll dis[N],d[N];
bool vis[N];
bool spfa(int s)
{
fill(dis,dis+n+1,inf);
dis[s]=0,vis[s]=1;
queue<int>q;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(auto t : e[u])
{
int v=t.first,w=t.second;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(!vis[v])
{
q.push(v);
vis[v]=1;
num[v]++;
if(num[v]==n+1)
return 0;
}
}
}
}
return 1;
}
void dij(int s)
{
fill(d,d+1+n,inf);
fill(vis,vis+1+n,0);
d[s]=0;
priority_queue<pii,vector<pii>,greater<pii> >q;
q.push({0,s});
while(!q.empty())
{
int u=q.top().second;
q.pop();
if(vis[u]) continue;
vis[u]=1;
for(auto t : e[u])
{
int v=t.first,w=t.second;
if(d[v]>d[u]+w)
{
d[v]=d[u]+w;
q.push({d[v],v});
}
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
e[u].push_back({v,w});
}
for(int i=1;i<=n;i++)
e[n+1].push_back({i,0});
if(!spfa(n+1))
return puts("-1"),0;
for(int i=1;i<=n;i++)
for(auto &t: e[i])
t.second+=dis[i]-dis[t.first];
for(int i=1;i<=n;i++)
{
dij(i);
ll ans=0;
for(int j=1;j<=n;j++)
if(d[j]==inf) ans+=1ll*1e9*j;
else ans+=(d[j]+dis[j]-dis[i])*j;
printf("%lld\n",ans);
}
return 0;
}
連通性問題
割點
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
vector<int>e[N];
int n,m;
int dfn[N],low[N],buc[N],tim;
void tarjan(int u,int fa)
{
dfn[u]=low[u]=++tim;
int son=0;
for(auto v : e[u])
{
if(v==fa) continue;
if(!dfn[v])
{
son++,tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]&&fa!=0) buc[u]=1;
}
else low[u]=min(low[u],dfn[v]);
}
if(son>=2&&fa==0) buc[u]=1;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
e[u].push_back(v),e[v].push_back(u);
}
for(int i=1;i<=n;i++)
{
if(!dfn[i]) tarjan(i,0);
}
int ans=0;
for(int i=1;i<=n;i++) ans+=buc[i];
printf("%d\n",ans);
for(int i=1;i<=n;i++)
if(buc[i]) printf("%d ",i);
return 0;
}
割邊
code:
#include<bits/stdc++.h>
#define pii pair<int,int>
using namespace std;
const int N=1e6+10;
int n,m;
vector<pii>e[N];
int tim,dfn[N],stk[N],top,low[N],tot;
vector<int>ans[N];
void form(int u)
{
++tot;
do{ans[tot].push_back(stk[top]);}
while(stk[top--]!=u);
}
void tarjan(int u,int fa)
{
dfn[u]=low[u]=++tim;
stk[++top]=u;
for(auto t : e[u])
{
if(t.second==fa) continue;
int v=t.first;
if(!dfn[v])
{
tarjan(v,t.second);
low[u]=min(low[u],low[v]);
if(dfn[u]<low[v]) form(v);
}
else low[u]=min(low[u],dfn[v]);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
e[u].push_back({v,i}),e[v].push_back({u,i});
}
for(int i=1;i<=n;i++)
if(!dfn[i]) tarjan(i,0),form(i);
printf("%d\n",tot);
for(int i=1;i<=tot;i++)
{
printf("%d ",ans[i].size());
for(auto v : ans[i]) printf("%d ",v);
puts("");
}
return 0;
}
樹上相關
最近公共祖先
倍增法(O(nlogn)-O(logn)):
#include<bits/stdc++.h>
using namespace std;
const int N=2e6+10;
struct getlca
{
int las[N],to[N],cut,nxt[N],c[N];
int dep[N],f[N][20];
void add(int u,int v)
{
cut++;
nxt[cut]=las[u];
las[u]=cut;
to[cut]=v;
}
void init(int u,int fa)
{
dep[u]=dep[fa]+1;
f[u][0]=fa;
for(int i=1;i<=19;i++)
f[u][i]=f[f[u][i-1]][i-1];
for(int e=las[u];e;e=nxt[e])
{
int v=to[e];
if(fa==v)continue;
init(v,u);
}
}
int lca(int u,int v)
{
if(dep[u]<dep[v])swap(u,v);
for(int i=19;i>=0;i--)
if(dep[u]-(1<<i)>=dep[v])u=f[u][i];
if(v==u) return u;
for(int i=19;i>=0;i--)
{
if(f[u][i]!=f[v][i])
u=f[u][i],v=f[v][i];
}
return f[u][0];
}
}T;
int n,m,st;
int main()
{
cin>>n>>m>>st;
for(int i=1;i<n;i++)
{
int u,v;
cin>>u>>v;
T.add(u,v),T.add(v,u);
}
T.init(st,0);
while(m--)
{
int u,v;
cin>>u>>v;
cout<<T.lca(u,v)<<endl;
}
return 0;
}
tarjan(離線)(O(n)-O(n)):
#include<bits/stdc++.h>
#define pii pair<int,int>
using namespace std;
const int N=5e5+10;
int n,m,s;
vector<int>e[N];
vector<pii>q[N];
int fa[N],dep[N],ans[N];
bool vis[N];
int find(int x)
{
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
void uni(int x,int y)
{
x=find(x),y=find(y);
if(dep[x]>dep[y]) fa[x]=y;
else fa[y]=x;
}
void tarjan(int u,int fa)
{
dep[u]=dep[fa]+1;
vis[u]=1;
for(auto v : e[u])
{
if(v==fa) continue;
tarjan(v,u);
uni(u,v);
}
for(auto t : q[u])
if(vis[t.first]) ans[t.second]=find(t.first);
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<=n;i++) fa[i]=i;
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
for(int i=1;i<=m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
q[u].push_back({v,i});
q[v].push_back({u,i});
}
tarjan(s,0);
for(int i=1;i<=m;i++)
printf("%d\n",ans[i]);
return 0;
}
dfs 序 + st 表(O(nlogn)-O(1)):
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
vector<int>e[N];
int n,m,s;
struct getlca
{
int f[20][N],tot=0,dfn[N];
void init(int u,int fa)
{
dfn[u]=++tot;
f[0][tot]=fa;
for(auto v : e[u])
{
if(v==fa) continue;
init(v,u);
}
}
int get(int u,int v){return dfn[u]<dfn[v]?u:v;}
int lca(int u,int v)
{
if(u==v) return u;
if(dfn[u]>dfn[v]) swap(u,v);
u=dfn[u]+1,v=dfn[v];
int t=log2(v-u+1);
return get(f[t][u],f[t][v-(1<<t)+1]);
}
}T;
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(int i=1;i<n;i++)
{
int u,v;
scanf("%d%d",&u,&v);
e[u].push_back(v);
e[v].push_back(u);
}
T.init(s,0);
for(int i=1;i<=19;i++)
for(int j=1;j<=n;j++)
T.f[i][j]=T.get(T.f[i-1][j],T.f[i-1][j+(1<<i-1)]);
while(m--)
{
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",T.lca(u,v));
}
return 0;
}
網路流
最大流
dinic 演算法。
#include<bits/stdc++.h>
using namespace std;
const int N=200+10,M=5e3+10;
int n,m,S,T;
struct dinic
{
int las[N],to[M<<1],nxt[M<<1],lim[M<<1],cnt=1;
void add(int u,int v,int li)
{
nxt[++cnt]=las[u];
las[u]=cnt;
to[cnt]=v;
lim[cnt]=li;
}
int cur[N],dis[N],fr[N],fl[N];
long long dfs(int u,long long res)
{
if(u==T) return res;
long long flow=0;
for(int i=las[u];i&&res;i=nxt[i])
{
cur[u]=i;
int c=min((long long)lim[i],res),v=to[i];
if(dis[v]==dis[u]+1&&c)
{
int k=dfs(v,c);
flow+=k,lim[i]-=k,lim[i^1]+=k,res-=k;
}
}
if(!flow) dis[u]=-1;
return flow;
}
long long maxflow(int s,int t)
{
long long flow=0;
while(1)
{
memcpy(cur,las,sizeof las);
memset(dis,-1,sizeof dis);
queue<int>q;
q.push(s);
dis[s]=0;
while(!q.empty())
{
int u=q.front();q.pop();
for(int i=las[u];i;i=nxt[i])
{
int v=to[i];
if(lim[i]&&dis[v]==-1)
{
dis[v]=dis[u]+1;
q.push(v);
}
}
}
if(dis[t]==-1) return flow;
flow+=dfs(s,1e18);
}
}
}G;
int main()
{
scanf("%d%d%d%d",&n,&m,&S,&T);
for(int i=1;i<=m;i++)
{
int u,v,li;
scanf("%d%d%d",&u,&v,&li);
G.add(u,v,li),G.add(v,u,0);
}
printf("%lld",G.maxflow(S,T));
return 0;
}
最小費用最大流
SSP 演算法。
注意點:
-
鏈式前向星的
cnt
一定從 \(1\) 開始,因為要成對變換。 -
每增廣路一次就要初始化。
-
SPFA 在隊首為 \(T\) 時不能直接 break,因為第一次取出 \(T\) 時 \(dis[T]\) 不一定取到最短路。
#include<bits/stdc++.h>
#define pii pair<int,int>
using namespace std;
const int N=5e3+10,M=5e4+10;
int n,m,S,T;
struct SSP
{
int las[N],nxt[M<<1],to[M<<1],c[M<<1],lim[M<<1],cnt=1;
void add(int u,int v,int w,int li)
{
nxt[++cnt]=las[u];
las[u]=cnt;
to[cnt]=v;
c[cnt]=w;
lim[cnt]=li;
}
int fl[N],fr[N],vis[N],dis[N];
pii mincost(int s,int t)
{
int flow=0,cost=0;
while(1)
{
memset(dis,0x3f,sizeof dis);
memset(vis,0,sizeof vis);
dis[s]=0,fl[s]=1e9;
queue<int>q;
q.push(s);
vis[s]=1;
while(!q.empty())
{
int u=q.front();q.pop();
vis[u]=0;
for(int i=las[u];i;i=nxt[i])
{
int v=to[i];
if(dis[v]>dis[u]+c[i]&&lim[i])
{
dis[v]=dis[u]+c[i];
fr[v]=i;
fl[v]=min(fl[u],lim[i]);
if(!vis[v]) vis[v]=1,q.push(v);
}
}
}
if(dis[t]>1e9) return {flow,cost};
flow+=fl[t],cost+=fl[t]*dis[t];
for(int u=t;u!=s;u=to[fr[u]^1])
lim[fr[u]]-=fl[t],lim[fr[u]^1]+=fl[t];
}
}
}G;
int main()
{
scanf("%d%d%d%d",&n,&m,&S,&T);
for(int i=1;i<=m;i++)
{
int u,v,w,li;
scanf("%d%d%d%d",&u,&v,&li,&w);
G.add(u,v,w,li),G.add(v,u,-w,0);
}
auto ans=G.mincost(S,T);
printf("%d %d",ans.first,ans.second);
return 0;
}
數學
矩陣相關
高斯消元
以SDOI2006 線性方程組為模板。
#include<bits/stdc++.h>
using namespace std;
const double eps=1e-8;
double a[110][110];
int n;
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
for(int j=1;j<=n+1;j++)
cin>>a[i][j];
int r=1;
for(int i=1;i<=n;i++)
{
int t=r;
for(int j=r+1;j<=n;j++)
if(fabs(a[j][i])>fabs(a[t][i])) t=j;
if(fabs(a[t][i])<eps) continue;
for(int j=i;j<=n+1;j++)
swap(a[r][j],a[t][j]);
for(int j=n+1;j>=i;j--)
a[r][j]/=a[r][i];
for(int j=r+1;j<=n;j++)
for(int z=n+1;z>=i;z--)
a[j][z]-=a[j][i]*a[r][z];
r++;
}
if(r<=n)
{
for(int i=r;i<=n+1;i++)
if(fabs(a[i][n+1])>eps)
return puts("-1"),0;
return puts("0"),0;
}
for(int i=n-1;i>=1;i--)
for(int j=i+1;j<=n;j++)
a[i][n+1]-=a[j][n+1]*a[i][j];
for(int i=1;i<=n;i++)
printf("x%d=%.2lf\n",i,a[i][n+1]);
return 0;
}
同餘相關
擴充套件中國剩餘定理
#include<bits/stdc++.h>
using namespace std;
typedef __int128_t ll;
const int N=1e7+10;
ll gcd(ll aa,ll bb)
{
if(!bb) return aa;
return gcd(bb,aa%bb);
}
ll lcm(ll aa,ll bb)
{
return aa/gcd(aa,bb)*bb;
}
ll exgcd(ll aa,ll bb,ll &x,ll &y)
{
if(!bb)
{
x=1,y=1;
return aa;
}
ll d=exgcd(bb,aa%bb,x,y);
ll z=x;
x=y;
y=z-(aa/bb)*y;
return d;
}
long long a[N],b[N],n;
int main()
{
scanf("%lld",&n);
for(int i=1;i<=n;i++)
scanf("%lld%lld",&a[i],&b[i]);
ll a1=a[1],b1=b[1];
for(int i=2;i<=n;i++)
{
ll a2=a[i],b2=b[i],x,y;
ll c=b2-b1;
ll d=exgcd(a1,a2,x,y);
if(c%d)
return puts("-1"),0;
c/=d;
x=x*c%(a2/d);
if(x<0) x+=(a2/d);
ll mod=lcm(a1,a2);
b1=(a1*x+b1)%mod;
if(b1<mod) b1+=mod;
a1=mod;
//printf("a b %lld %lld\n",(long long)a1,(long long)b1);
}
printf("%lld",(long long)((b1%a1)+a1)%a1);
return 0;
}