题目链接:传送门
思路:
1、如果点数大于1000,结果就是n-1;但是如果L==R,结果就是(n-1)*L;
2、如果n小于等于1000,跑kruskal。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1005;
struct Edge
{
int u,v,w;
};
vector <Edge> vc;
int n,L,R,a[N],fa[N] = {0};
unsigned long long seed;
unsigned long long xorshift64()
{
unsigned long long x = seed;
x ^= x << 13;
x ^= x >> 7;
x ^= x << 17;
return seed = x;
}
int gen()
{
return xorshift64() % (R-L+1) + L;
}
bool cmp(Edge a,Edge b)
{
return a.w < b.w;
}
int f(int x)
{
if(fa[x] == 0) return x;
fa[x] = f(fa[x]);
return fa[x];
}
ll kruskal()
{
sort(vc.begin(),vc.end(),cmp);
ll ans = 0;
for(auto it:vc){
int u = it.u,v = it.v,w = it.w;
int t1 = f(u),t2 = f(v);
if(t1 != t2){
fa[t2] = t1;
ans += w;
}
}
return ans;
}
int main(void)
{
scanf("%d%d%d%llu",&n,&L,&R,&seed);
if(n>1000){
ll ans = 0;
if(L == R) ans = 1LL*(n-1)*L;
else ans = 1LL*(n-1);
printf("%lld\n",ans);
return 0;
}
for(int i=1;i<=n;i++){
a[i] = gen();
for(int j=1;j<i;j++){
int g = __gcd(a[i],a[j]);
vc.push_back({i,j,g});
vc.push_back({j,i,g});
}
}
printf("%lld\n",kruskal());
return 0;
}