Title set address Asian regional competition of the 46th ICPC international college student programming competition (Shanghai)
The first training during the holiday, the effect was good, and I did two sign in questions of DE
This supplementary question:
DE (sign in)
G (DP on tree)
I (DP)
J (bit operation)
K (structure)
D Strange_Fractions thinking + mathematics
Title address D Strange_Fractions
Give a score
p
q
\frac{p}{q}
qp, now find two positive integers a, B, a, Ba, B to make the equation
p
q
=
a
b
+
b
a
\frac{p}{q}=\frac{a}{b}+\frac{b}{a}
qp = ba + ab, if there is no solution, two zeros are output
Idea: transform the original problem and set
x
=
a
b
,
t
=
p
q
x=\frac{a}{b},t=\frac{p}{q}
x=ba, t=qp, then the original equation can become
x
+
1
x
=
t
x+\frac{1}{x}=t
x+x1 = t, which is equivalent to solving the equation
x
2
−
t
x
+
1
=
0
x^2-tx+1=0
x2 − tx+1=0, the solution is
x
=
t
±
(
t
2
−
4
)
2
x=\frac{t±\sqrt{(t^2-4)}}{2}
x=2t±(t2−4)
, we can see that the problem condition is rational number solution, then
(
t
2
−
4
)
\sqrt{(t^2-4)}
(t2−4)
It must be a rational number, and the resulting solutions correspond to each other
a
b
,
b
a
\frac{a}{b},\frac{b}{a}
ba, ab, so directly bring the given q,p into the equation to find the solution and judge whether it is a rational number solution. If so, further convert the obtained solution into fractional form to obtain a,b.
AC Code:
#include <bits/stdc++.h> #include <iostream> #include <cstring> #include <stdlib.h> #include <stdio.h> #define ll long long #define INF 0x3f3f3f3f using namespace std; const int maxn = 1e5+10; const int mod = 1e9+7; ll gcd(ll a,ll b) { if(a<b) swap(a,b); ll yu; yu=a%b; while(true) { a=b; b=yu; if(yu==0) break; yu=a%b; } return a; } void solve() { bool bol=true; ll p,q; scanf("%lld%lld",&p,&q); ll k=p*p-4*q*q; ll kk=sqrt(k); if(kk*kk==k) bol=true; else bol=false; ll gcdd=gcd(p-kk,q*2); if(!bol) printf("0 0\n"); else { printf("%lld %lld\n",(p-kk)/gcdd,q*2/gcdd); } } int main() { int t = 1; scanf("%d",&t); while(t--) { solve(); } return 0; }
E Strange_Integers thinking
Title address E Strange_Integers
Given a sequence with a length of n, select m numbers from the sequence. If the absolute value of the difference between any two numbers in the M numbers is greater than or equal to the value of k, ask the maximum value of M
Idea: sort the original sequence, first select a minimum value T, and then find the minimum value greater than or equal to t+k from the sequence until the whole sequence is searched, and the number of numbers found is the maximum m value
AC Code:
#include <bits/stdc++.h> #define ll long long #define INF 0x3f3f3f3f using namespace std; const int N = 1e5+5; int a[N]; void solve() { int n,k; scanf("%d%d",&n,&k); for(int i = 1;i <= n;i++) { scanf("%d",a+i); } sort(a+1,a+n+1); int ans = 0; int t = a[1]; int pos = 1; while(pos!=n+1) { t=a[pos]; t+=k; ans++; pos = lower_bound(a+1,a+1+n,t)-a; } printf("%d\n",ans); } int main() { int t = 1; while(t--) { solve(); } return 0; }
G Edge Groups thinking + Math
Title address G Edge Groups
An undirected connected graph with n points and N-1 edges is given. N must be an odd number. Now n-1 edges are divided into (n-1)/2 groups. The conditions for each group are as follows: a group has only two edges, and the two edges have one thing in common. The number of schemes of all grouping schemes that meet the conditions is output. The result of modulo 998244353 is obtained
Idea: a tree with n (odd) points is divided into n − 1 edges n − 1 2 \frac{n−1}{2} 2n − 1 group, each group has two sides, and the two sides should have a common point. Ask the number of schemes in the group. If there are even points in subtree x, the odd edges must not be grouped, and X needs to be connected to its father's edge. If there are an odd number of points, even edges can be grouped.
Let d[x] be the number of schemes for grouping the edges in the subtree of X. let a y of child y of X need (x,y) this edge to be paired with the edge in the subtree of Y, and b y are paired with (x,y) here. Then when B is odd, we also need the edge connected by X to its father. That is, X has an even number of a subtree points and an odd number of B subtree points. Now we only need to consider grouping B subtrees in pairs. If B is odd, then (x,fa) needs to be added.
d
[
x
]
=
{
f
[
b
]
∗
∏
d
[
y
]
f
[
b
+
1
]
∗
∏
d
[
y
]
d[x]=\left\{ \begin{matrix} f[b]*\prod{d[y]} \\ f[b+1]*\prod{d[y]} \end{matrix} \right.
d[x]={f[b]∗∏d[y]f[b+1]∗∏d[y]
n elements, two in each group
n
2
\frac{n}{2}
The number of schemes of 2n group is f[n], and there is a recursive formula f[n]=f[n − 2] * (n − 1).
AC Code:
#include <bits/stdc++.h> using namespace std; #define rep(i,j,k) for(int i=int(j);i<=int(k);i++) #define per(i,j,k) for(int i=int(j);i>=int(k);i--) typedef long long ll; const int N = 100010, mod = 998244353; int n, sz[N]; vector<int> g[N]; ll d[N], f[N]; void dfs(int x, int fa) { sz[x] = 1; d[x] = 1; int cnt = 0; for(auto &y : g[x]) { if(y == fa) continue; dfs(y, x); sz[x] += sz[y]; d[x] = d[x] * d[y] % mod; if(sz[y] & 1) cnt ++; } if(cnt & 1) cnt ++; d[x] = d[x] * f[cnt] % mod; } int main() { scanf("%d", &n); for(int i=1; i<n; i++) { int x, y; scanf("%d%d", &x, &y); g[x].push_back(y); g[y].push_back(x); } f[0] = 1; for(int i=2; i<=n; i+=2) { f[i] = f[i-2] * (i-1) % mod; } dfs(3, 0);//In fact, any node can be used as the root node. In fact, it is also possible to traverse with other nodes as the root node printf("%lld\n", d[3]); return 0; }
I Steadily Growing Steam DP
Title address I Steadily Growing Steam
Main idea of the title: give n cards. Each card has a digital label and a value. You can choose at least s cards to double the digital label. Now select two groups of cards from the doubled cards to make the sum of the digital labels equal and the value and maximum
Idea: it can be regarded as 01 knapsack problem and use dynamic programming.
dp[i][j][k], from the previous I cards, use the skill at most j times. The difference + 2600 of the sum of ti of the two groups of cards is K. The reason why K is defined as difference + 2600 is that the minimum difference is - 2600. Prevent the subscript of the array from being negative and add an offset. According to different situations: put S not to double, put S to double, put T not to double, and put T to double to directly transfer the state
AC Code:
#include <bits/stdc++.h> using namespace std; typedef long long ll; ll n,s,dp[101][101][5201],v[101],t[101]; const int inf=0x3f3f3f3f; int main() { ios::sync_with_stdio(0); cin.tie(0); cin >>n>>s; for(int i=1; i<=n; i++) cin >>v[i]>>t[i]; for(int i=0; i<=s; i++)//initialization for(int j=0; j<=5200; j++) dp[0][i][j]=-inf*(j!=2600); //This place cannot move 2600, because 2600 is the solution, and the solution is 0 at the beginning for(int i=1; i<=n; i++) for(int j=0; j<=s; j++) for(int k=0; k<=5200; k++) { dp[i][j][k]=dp[i-1][j][k]; if(k>=t[i])dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k-t[i]]+v[i]); //Load T if(k+t[i]<=5200)dp[i][j][k]=max(dp[i][j][k],dp[i-1][j][k+t[i]]+v[i]); //Load S if(j&&k>=2*t[i])dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k-2*t[i]]+v[i]); //Load S after doubling if(j&&k+2*t[i]<=5200)dp[i][j][k]=max(dp[i][j][k],dp[i-1][j-1][k+2*t[i]]+v[i]); //Load T after doubling } cout <<dp[n][s][2600]<<endl; return 0; }