AC(c++)
E - Power of Points
You are given npoints with integer coordinates x1,…xn, which lie on a number line.
For some integer s, we construct segments [s,x1], [s,x2], ……, [s,xn]. Note that if xi<s, then the segment will look like [xi,s]. The segment [a,b] covers all integer points a,a+1,a+2,…,b.
We define the power of a point p as the number of segments that intersect the point with coordinate p, denoted as fp.
Your task is to compute ∑p=1109fpfor each s∈{x1,…,xn}, i.e., the sum of fp for all integer points from 11 to 109109.
For example, if the initial coordinates are [1,2,5,7,1] and we choose s=5, then the segments will be: [1,5],[2,5],[5,5],[5,7],[1,5]. And the powers of the points will be: f1=2,f2=3,f3=3,f4=3,f5=5,f6=1,f7=1,f8=0,…,f109=0. Their sum is 2+3+3+3+5+1+1=18.
If we have the segments [l1,r1],…,[ln,rn]
, the sum of fp
is the sum of the segments' lengths. That's because a segment [a,b]
intersect exactly b−a+1
points. Now we can find the answer for fixed s
in O(N)
.
How to do it more efficiently?
Let's sort the given points so that x1≤x2≤⋯≤xn
.
Processing s=xi
we get that for all j≤i
the segments are [xj,s]
and for all j>i
the segments are [s,xj]
. We need to summarize their lengths. Formally we need to calculate
∑j=1i(s−xj+1)+∑j=i+1n(xj−s+1)=
n+s⋅i−∑j=1ixj+∑j=i+1nxj−s(n−i)=
n+s(2⋅i−n)−∑j=1ixj+∑j=i+1nxj
We can maintain the sum of coordinates on the prefix and suffix, and calculate this formula for fixed s
in O(1)
.
The total complexity is O(nlogn)
.
#include<bits/stdc++.h>
using namespace std;
const int N=200005;
pair<int,int>x[N];
long long a[N];
int main()
{
int t;cin>>t;
while(t--)
{
int n;cin>>n;
long long s1=0,s2=0;
for(int i=1;i<=n;i++)
{
cin>>x[i].first;
x[i].second=i;
s2+=x[i].first;
}
sort(x+1,x+n+1);
for(int i=1;i<=n;i++)
{
s2-=x[i].first;
s1+=x[i].first;
a[x[i].second]=n+1ll*x[i].first*(2*i-n)-s1+s2;
}
for(int i=1;i<=n;i++)cout<<a[i]<<" \n"[i==n];
}
}
F - Sum and Product
You have an array a of length n.
Your task is to answer q queries: given x,y find the number of pairs i and j (1≤i<j≤n) that both ai+aj=x and ai⋅aj=y.
That is, for the array [1,3,2]and asking for x=3,y=2 the answer is 11:
- i=1 and j=2 fail because 1+3=4 and not 3, also 1⋅3=3and not 2;
- i=1 and j=3 satisfies both conditions;
- i=2 and j=3 fail because 3+2=5 and not 3, also 3⋅2=6 and not 2;
The system of equations in the statement resembles Vieta's formula for quadratic equations. If we have
{ai+aj=bai⋅aj=c
the quadratic equation will be x2−bx+c=0
, here ai
and aj
will be its roots.
To find the roots of the quadratic equation, we can use the discriminant formula, D=b2−4ac
. The roots will then be x1=b−D√2
and x2=b+D√2
.
Once we have the potential integer values for ai
and aj
, we can calculate the number of pairs by multiplying the number of occurrences, respectively.
However, remember to consider some special cases:
If D<0
, the equation won't have real roots.
If D=0
, then x1=x2
, the formula for counting pairs in this case is different.
The complexity of this solution is O((n+q)logn)
, using maps to store integer occurrences.
#include<bits/stdc++.h>
using namespace std;
map<long long,int>cnt;
long long my_sqrt(long long a)
{
long long l=0,r=5000000001;
while(r-l>1)
{
long long mid=(l+r)/2;
if(1ll*mid*mid<=a)l=mid;
else r=mid;
}
return l;
}
long long get(int b,long long c)
{
long long D=1ll*b*b-4ll*c;
if(D<0)return 0;
long long x1=(b-my_sqrt(D))/2;
long long x2=(b+my_sqrt(D))/2;
if(x1+x2!=b||x1*x2!=c)return 0;
if(x1==x2)return 1ll*cnt[x1]*(cnt[x1]-1)/2ll;
else return 1ll*cnt[x1]*cnt[x2];
}
int main()
{
int t;cin>>t;
while(t--)
{
int n;cin>>n;
cnt.clear();
for(int i=1;i<=n;i++)
{
int x;cin>>x;
cnt[x]++;
}
int q;cin>>q;
for(int i=0;i<q;i++)
{
int b;long long c;
cin>>b>>c;
cout<<get(b,c)<<" \n"[i==q-1];
}
}
}
G - Counting Graphs
Given a tree consisting of n vertices. A tree is a connected undirected graph without cycles. Each edge of the tree has its weight, wi.
Your task is to count the number of different graphs that satisfy all four conditions:
- The graph does not have self-loops and multiple edges.
- The weights on the edges of the graph are integers and do not exceed S.
- The graph has exactly one minimum spanning tree.
- The minimum spanning tree of the graph is the given tree.
Two graphs are considered different if their sets of edges are different, taking into account the weights of the edges.
The answer can be large, output it modulo 998244353998244353.
The first observation is that the graphs will consist of n
vertices because the MST is fixed. Hence, the graphs will look like the given tree with some new vertices connected.
The next step is to determine the possible weights of a new edge between vertices u
and v
. Let P(u,v)
be the maximum weight on the simple path from u
to v
. I assume that we can add a new edge between vertices u
and v
with any weight in the range [P(u,v)+1,S]
. This becomes clear when we consider some examples. If the edge has a weight less or equal than P(u,v)
, the MST will change by taking the new edge instead of the edge with the maximal weight on the path.
Notice that if we add a new edge, and it doesn't affect the MST, we can add one more edge independently from the previous.
So now the task is to calculate ∏1≤u<v≤n(S−P(u,v)+1)
, because for each pair of vertices, we can assign a new weight from the range, which gives us S−P(u,v)
cases, or we can choose not to add any edge, which is one more case.
Now, let's discuss how to calculate the formula efficiently:
Sort the given edges in ascending order according to their weights: w1≤w2≤⋯≤wn−1
.
We'll begin from the graph without edges, and add new ones step by step. Suppose, we already added all the edges up to ui,vi,wi
. Now, we want to add the i
-th one. Notice that wi
is greater than any of the weights before, and ui
and vi
are from different components.
After adding the edge, we need to calculate the number of paths that go through this edge. If we know the sizes of the components containing ui
and vi
, denoted as su
and sv
respectively, then there exist su⋅sv−1
paths through edge ui,vi
without including the path formed by these two vertices.
We know the number of paths, and on each of these paths, we can determine the weight we can put on the edge. Thus, we need to multiply answer by (S−wi+1)su⋅sv−1
, using binary exponentiation.
To add edges and find the sizes of the components efficiently, you can use DSU (Disjoint Set Union).
The complexity of this approach is O(nlogn)
.
#include<bits/stdc++.h>
using namespace std;
const int N=200000,mod=998244353;
int p[N+1],sz[N+1];
struct edge
{
int u,v,w;
void read(){cin>>u>>v>>w;}
bool operator<(edge x){return w<x.w;}
}a[N+1];
int leader(int v)
{
if(p[v]==v)return v;
else return p[v]=leader(p[v]);
}
void unite(int u,int v)
{
u=leader(u);
v=leader(v);
p[u]=v;
sz[v]+=sz[u];
}
long long binpow(long long a,long long n)
{
if(n==0)return 1;
if(n%2==0)return binpow(a*a%mod,n/2);
else return a*binpow(a,n-1)%mod;
}
int main()
{
int t;cin>>t;
while(t--)
{
int n,S;cin>>n>>S;
for(int i=1;i<=n;i++)p[i]=i,sz[i]=1;
for(int i=0;i<n-1;i++)a[i].read();
sort(a,a+n-1);
long long ans=1;
for(int i=0;i<n-1;i++)
{
int sub_u=sz[leader(a[i].u)];
int sub_v=sz[leader(a[i].v)];
ans=ans*binpow(S-a[i].w+1,1ll*sub_u*sub_v-1)%mod;
unite(a[i].u,a[i].v);
}
cout<<ans<<"\n";
}
}