T1
這是一個更相減損。
出現的所有的不同的數就是更相減損過程中出現的;
直接這樣做的話,會T或者爆;
再進一步分析一下,就會發現,我們可以把更相減損優化爲輾轉相除,因爲多幾次更相減損就是輾轉相除,那麼不同數的個數在輾轉相除中就是每次的a/b,因爲a只有減損a/b次纔會達到b,a%b的狀態,這之間的數是遞減的,不會出現重複。
T2
50分,我們可以倒着加邊,添加進新的邊時,用並查集維護,合併集合時,把每個集合新加進的點的個數記下來,這一輪結束後,ans[i]+=ad[i]*ad[i]就可以了。
100分:
用克魯斯卡爾算法求最大生成樹,在並查集合並時,把原本的一個根連向另一
個根改成兩個根都連向一個新建的節點,並把當前正在處理的邊的權值賦給這
個新節點做點權。這樣形成的結構會是一棵樹。
一個點的答案大致上是樹的根到自己的路徑上,相鄰兩個節點的子樹葉節
點數的平方和。需要注意的是父子兩個節點權值相同的情況,這個部分需要特
殊處理。(看代碼會比較容易理解)
T3
不是太會。
T1
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
using namespace std;
LL a1,a2,ans;
LL gcd(LL a,LL b)
{
if(!b) return a;
ans+=a/b;
return gcd(b,a%b);
}
int main()
{
freopen("seq.in","r",stdin);
freopen("seq.out","w",stdout);
scanf("%lld%lld",&a1,&a2);
if(a1<a2) swap(a1,a2);
gcd(a1,a2);
ans++;//0也算一種
printf("%lld\n",ans);
return 0;
}
T2
50分
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<ctime>
#define LL long long
using namespace std;
const int N=100009;
const int M=200009;
const int inf=(1e9);
int n,m;
struct H{
int x,y,z;
}e[M];
int a[M],cnt,f[N];
LL ans[N],siz[N],ad[N];
bool cmp(H w1,H w2)
{
return w1.z>w2.z;
}
int find(int x)
{
return f[x]==x?x:f[x]=find(f[x]);
}
void add(int o)
{
int fx=find(e[o].x);
int fy=find(e[o].y);
if(fx!=fy)
{
for(int i=1;i<=n;i++)
{
int ff=find(i);
if(ff==fx)
ad[i]+=siz[fy];
else
if(ff==fy)
ad[i]+=siz[fx];
}
f[fx]=fy;
siz[fy]+=siz[fx];
}
}
int main()
{
freopen("car.in","r",stdin);
freopen("car.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].x,&e[i].y,&e[i].z);
sort(e+1,e+m+1,cmp);
for(int i=1;i<=m;i++) if(e[i].z!=a[cnt]) a[++cnt]=e[i].z;
for(int i=1;i<=n;i++) f[i]=i,siz[i]=1;
int t=1;
for(int i=1;i<=cnt;i++)
{
int flag=0;
while(e[t].z>=a[i]&&t<=m)
{
add(t);
t++;
flag=1;
}
if(f)
for(int i=1;i<=n;i++)
{
ans[i]+=ad[i]*ad[i];
ad[i]=0;
}
if(t>m) break;
}
for(int i=1;i<=n;i++)
printf("%lld ",ans[i]);
return 0;
}
100分(打了一遍找不到了,貼標程吧qaq)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;
const int N = 510000;
typedef long long ll;
struct node
{
int u, v, l;
bool operator < (const node &no) const
{
return l > no.l;
}
}e[N];
int n, m, newn;
int son[N][2];
int fa[N], size[N], value[N];
ll ans[N];
int read()
{
char ch = getchar();
int x = 0;
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) {x = x*10+(ch-'0');ch=getchar();}
return x;
}
int getf(int x)
{
if (fa[x] == x) return x;
fa[x] = getf(fa[x]);
return fa[x];
}
void dfs(int u, int fa, ll cnt)
{
ll delta = 0;
if (fa)
{
if (value[u] == value[fa]) size[u] = size[fa];
else delta = (ll)(size[fa] - size[u]) * (ll)(size[fa] - size[u]);
}
if (son[u][0])
{
dfs(son[u][0], u, cnt + delta);
dfs(son[u][1], u, cnt + delta);
}
else ans[u] = cnt + delta;
}
int main()
{
freopen("car.in","r",stdin);
freopen("car.out","w",stdout);
n = read(), m = read();
for (int i = 1; i <= m; i++)
{
e[i].u = read();
e[i].v = read();
e[i].l = read();
}
sort(e + 1, e + 1 + m);
for (int i = 1; i <= n; i++) fa[i] = i;
newn = n;
for (int i = 1; i <= n; i++) size[i] = 1;
for (int i = 1; i <= m; i++)
{
int u = getf(e[i].u), v = getf(e[i].v);
if (u == v) continue;
newn++;
son[newn][0] = u;
son[newn][1] = v;
fa[u] = fa[v] = newn;
fa[newn] = newn;
value[newn] = e[i].l;
size[newn] = size[u] + size[v];
}
dfs(newn, 0, 0);
for (int i = 1; i <= n; i++)
printf("%lld ", ans[i]);
printf("\n");
return 0;
}