** It is hereby declared that , This document is for reference only , Please refer to official documents for standard answers **
test questions A

This question is a knapsack dp topic , My idea is to define 3D dp, The first dimension represents the second dimension i number , The second dimension represents the front i The sum of the numbers is j, The third dimension represents the front i number , The sum is j, Section i The number is z Number of schemes .

First observe the nature of the problem , Different requirements , First we need to find a strictly increasing sequence , And the sum of the sequences is 2022
I thought of it at first O(n3) of dp state transition , But we found that one dimension can be optimized to become O(n2)dp, And then successfully work out the answer .
It should be noted that the l o n g l o n g long long longlong Because the answer is too big int

Then the equation is derived ：
i f ( k > z ) c o n t i n u e ; / / surface bright When front total and pretend no lower When front term if(k > z)
continue ; // Indicates that the current sum cannot fit the current item if(k>z)continue;// Indicates that the current sum cannot fit the current item
i f ( k a n d z > = k ) / / I Men can with to When front Pieces lift term plus one structure make new of square case if(k and z >=
k) // We can add a new scheme to the current enumeration if(kandz>=k)// We can add a new scheme to the current enumeration
f [ i ] [ z ] [ k ] + = f [ i − 1 ] [ z − k ] [ k − 1 ] ; f[i][z][k] += f[i -
1][z - k][k - 1] ;f[i][z][k]+=f[i−1][z−k][k−1];
i f ( z a n d k ) / / surface bright I Men choose of When front term have to must than upper one term strict grid large if(z and
k)// Indicates that the current item we selected must be greater than the previous one if(zandk)// Indicates that the current item we selected must be greater than the previous one
f [ i ] [ z ] [ k ] + = f [ i ] [ z − 1 ] [ k − 1 ] ; f[i][z][k] += f[i][z -
1][k - 1] ;f[i][z][k]+=f[i][z−1][k−1];

The code is as follows
#include <iostream> #include <cstring> #include <cmath> using namespace std ;
long long ans ; long long f[20][3000][3000] ; // number the sum Previous int main(void){ f[0][
0][0] = 1 ; for(int i = 1 ; i <= 10 ; i ++) for(int z = 0 ; z <= 2022 ; z ++)
for(int k = 0 ; k <= 2022 ; k ++){ if(k > z) continue ; if(k && z >= k) f[i][z][
k] += f[i - 1][z - k][k - 1] ; if(z && k) f[i][z][k] += f[i][z - 1][k - 1] ; }
for(int i = 0 ; i <= 2022 ; i ++) ans += f[10][2022][i] ; cout << ans << endl ;
}
379187662194355221
test questions B

First of all, we can observe that , This is an enumeration topic , Violence enumeration .
The main points of attention are , In the course of one revolution of the hour hand , Every pass 1 s 1s 1s The angle of rotation is 360 ∗ ( 1 / ( 60 ∗ 60 ∗ 12 ) ) 360 *
(1 / (60 * 60 * 12) )360∗(1/(60∗60∗12)), We need to calculate the rotation angle per second . In the process of the minute hand turning around , Every pass 1 s 1s 1
s The angle of rotation is 360 ∗ ( 1 / ( 60 ∗ 60 ) ) 360 * (1 / (60 * 60) ) 360∗(1/(60∗60)) , Second is
360 ∗ ( 1 / 60 ) 360 * (1 / 60)360∗(1/60) .

So we can run my code happily , There are only two findings , One is 0 , 0 , 0 0 ,0,0 0,0,0 , One is 4 , 48 , 0 4,48,0
4,48,0.[ , , , Represents a space ]
4 48 0
The code is as follows
#include <iostream> #include <cstring> #include <cmath> using namespace std ;
const double eps = 1e-8 ; double get(int a , int b , int c){ return 360.0 * (a *
3600 + b * 60 + c) / (3600 * 12) ; } double get(int b , int c){ return 360.0 * (
b* 60 + c) / 3600 ; } double get(int c){ return 360.0 * c / 60 ; } int main(void
){ // cout << get(30 , 0) << endl ; for(int i = 0 ; i <= 6 ; i ++) for(int j = 0
; j <= 59 ; j ++) for(int z = 0 ; z <= 59 ; z ++){ double a = get(i , j , z) ;
double b = get(j , z) ; double c = get(z) ; double x = abs(a - b) ; double y =
abs(c - b) ; if(x > 180) x = 360 - x ; if(y > 180) y = 360 - y ; if(fabs(x - 2 *
y) < eps){ cout << i << " " << j << " " << z << endl ; } } }
test questions C

First look at this topic , We can see that this is similar to the idea of greed .
We must fill the smallest hole first , Similar to irrigation , Then slowly count the layers .
Our first strategy is to sort first , Sort by size from small to large .
But there is an array in the title b limit , We can't simply solve the answer .
But how do we use arrays b And , We found that ai + bi Is the maximum number of layers that can be placed in this column .
m i n ( a i + b i ) i by [ 1 , n ] min(ai + bi) i by [1 , n] min(ai+bi)i by [1,n]
This is the maximum value of the answer

And then we sort it out , We start our simulation process , Because the sequence is increasing , So we simulate the irrigation process one by one according to the height order . The final answer a n s ans
ans To add a [ 1 ] a[1] a[1] Indicates the maximum height that can be obtained only by irrigation at present .

And the end result is m i n ( a n s + a [ 1 ] , a n s 1 ) min(ans + a[1] , ans1) min(ans+a[
1],ans1)
When considering the data 2e5 When , Using fast read will significantly improve the running speed of code .

The code is as follows
#include <iostream> #include <cstring> #include <cmath> #include <algorithm>
using namespace std; typedef long long LL ; const int N = 2e5 + 10 ; const int
Inf= 1e9 + 10 ; int a[N] , b[N] ; int read(){ int res = 0 , flag = 1 ; char c =
getchar() ; while(!isdigit(c)){ if(c == '-') flag = -1 ; c = getchar() ; } while
(isdigit(c)){ res = (res << 1) + (res << 3) + (c ^ 48) ; c = getchar() ; }
return res * flag ; } int main(void){ int n ; LL m ; scanf("%d%lld" , &n , &m) ;
for(int i = 1 ; i <= n ; i ++) a[i] = read() ; for(int i = 1 ; i <= n ; i ++) b[
i] = read() ; int ans = a[1] + b[1] ; for(int i = 2 ; i <= n ; i ++) ans = min(
ans, a[i] + b[i]) ; sort(a + 1 , a + 1 + n) ; int ans1 = 0 ; a[n + 1] = Inf ;
for(int i = 1 ; i <= n ; i ++){ int j = i ; while(j <= n && a[i] == a[j]) j ++ ;
j-- ; long long tot = (a[j + 1] - a[j]) * 1ll * j ; if(m >= tot) { ans1 += a[j
+ 1] - a[j] ; m -= tot ; } else { ans1 += m / j ; break ; } i = j ; } printf(
"%d\n" , min(ans , ans1 + a[1])) ; return 0 ; }
test questions D

This problem should be an obscure Backpack dp .
The idea is as follows
First, let's find the backpack dp Two conditions required , One is cost w w w, One is value v v v
First of all, we can observe that the two methods of this topic are plus plus Additive sum reduce reduce reduce , We can think of this as a group knapsack model , Then the cost is the minimum number of times it takes to reach a certain number .
The calculation method is as follows
int get(int x , int mod){ return (x % mod + mod) % mod ; } for(int p = 0 ; p
<= 9 ; p ++) { int t = s[i] - '0' ; int x = get(p - t , 10) ; int y = get(t - p
, 10) ; }
p It is the number that we enumerate the current position , Then we started talking about value , The value of putting numbers first is , We take the length of the whole number as n , The value of the first number is 10 n-1 * p .
The value of the remaining figures and so on .

So a backpack that wasn't obvious dp The code of is as follows
be careful ： This question needs to be answered long long
#include <iostream> #include <cstring> #include <cmath> #include <algorithm>
using namespace std ; const int N = 20 ; const int M = 110 ; typedef long long
LL; LL f[N][M][M] ; char s[N] ; int a , b ; long long f10[20] ; int get(int x ,
int mod){ return (x % mod + mod) % mod ; } int main(void){ scanf("%s" , s + 1) ;
scanf("%d%d" , &a , &b) ; f10[0] = 1 ; for(int i = 1 ; i <= 18 ; i ++) f10[i] =
f10[i - 1] * 10 ; int n = strlen(s + 1) ; for(int i = 1 ; i <= n ; i ++) for(int
p= 0 ; p <= 9 ; p ++) { int t = s[i] - '0' ; int x = get(p - t , 10) ; int y =
get(t - p , 10) ; for(int j = 0 ; j <= a ; j ++) for(int k = 0 ; k <= b ; k ++){
if(j >= x) f[i][j][k] = max(f[i][j][k] , f[i - 1][j - x][k] + f10[n - i] * p) ;
if(k >= y) f[i][j][k] = max(f[i][j][k] , f[i - 1][j][k - y] + f10[n - i] * p) ;
} } printf("%lld" , f[n][a][b]) ; return 0 ; }
test questions E

First, in the description of the problem, we can already observe that the problem is a bare single source shortest path problem , But there is an isolation time limit , We need to change some variables of the single source shortest path to meet the problem requirements , First, we observe that the value of edges has changed , from i
- j We should be the price of the road +j Isolation time of , Then we can find the solution by running the shortest path through the current graph , But if the price of the side is a point, go to the end n n n
The cost of is no longer the edge weight plus the current isolation time , Because we don't need to isolate from the end to the next point .
Edging process
for(int i = 1 ; i <= m ; i ++){ int a , b , c; scanf("%d%d%d" , &a , &b , &c) ;
if(b != n) add(a , b , c + ci[b]) ; else add(a , b , c) ; if(a != n) add(b , a ,
c+ ci[a]) ; else add(b , a , c) ; }
The code is as follows
#include <iostream> #include <cstring> #include <cmath> #include <algorithm> #
include <queue> #define x first #define y second using namespace std ; const int
N= 1e5 + 10 ; const int M = 2 * N ; typedef pair<int , int> PII ; int h[N] , e[
M] , ne[M] , idx ; int w[M] , ci[N] ; bool st[N] ; int dist[N] ; int read(){ int
res= 0 , flag = 1 ; char c = getchar() ; while(!isdigit(c)){ if(c == '-') flag
= -1 ; c = getchar() ; } while(isdigit(c)){ res = (res << 1) + (res << 3) + (c ^
48) ; c = getchar() ; } return res * flag ; } void add(int a , int b , int c) {
e[idx] = b , w[idx] = c , ne[idx] = h[a] , h[a] = idx ++ ; } int main(){ memset(
h, -1 , sizeof h) ; int n , m ; scanf("%d%d" , &n , &m) ; for(int i = 1 ; i <= n
; i ++) ci[i] = read() ; for(int i = 1 ; i <= m ; i ++){ int a , b , c; scanf(
"%d%d%d" , &a , &b , &c) ; if(b != n) add(a , b , c + ci[b]) ; else add(a , b ,
c) ; if(a != n) add(b , a , c + ci[a]) ; else add(b , a , c) ; } memset(dist ,
0x3f ,sizeof dist) ; priority_queue<PII , vector<PII> , greater<PII>> q ; dist[1
] = 0 ; q.push({0 , 1}) ; PII t ; while(q.size()){ t = q.top() ; q.pop() ; int d
= t.x , ver = t.y ; if(st[ver]) continue ; st[ver] = true ; for(int i = h[ver] ;
~i ; i = ne[i]){ int j = e[i] ; if(dist[ver] + w[i] < dist[j]){ dist[j] = dist[
ver] + w[i] ; q.push({dist[j] , j}) ; } } } printf("%d" , dist[n]) ; return 0 ;
}
test questions F

This is a very conspicuous Backpack dp.
This is a kind of judgment Backpack dp, Judge whether it can form a certain number or not dp.
Define two dimensions dp , Before representation i Can be composed of j.
The state transition equation is
i f ( i > = k a n d j > = c o s t [ c n t ] . y ) f [ i ] [ j ] ∣ = f [ i − k
] [ j − c o s t [ c n t ] . y ] ; if(i >= k and j >= cost[cnt].y) f[i][j] |=
f[i - k][j - cost[cnt].y] ;if(i>=kandj>=cost[cnt].y)f[i][j]∣=f[i−k][j−cost[cnt].
y];
e l s e i f ( i < k a n d j = = c o s t [ c n t ] . y ) else if(i < k and j
== cost[cnt].y)elseif(i<kandj==cost[cnt].y)
f [ i ] [ j ] ∣ = t r u e ; f[i][j] |= true ; f[i][j]∣=true;
The detail to be noted is that enumerating from back to front is the closest m Answer to .

So the code is as follows
#include <iostream> #include <cstring> #include <cmath> #include <algorithm> #
define x first #define y second using namespace std ; const int N = 20 ; const
int M = 8010 ; const int K = 1010 ; const int Inf = 1e9 + 10 ; typedef pair<int
, int> PII ; int day[N] = {0 , 31 , 28 , 31 , 30 , 31 , 30 , 31 , 31 , 30 , 31 ,
30 , 31} ; PII cost[M] ; int f[K][M] ; int get(int a , int b){ return day[a - 1]
+ b ; } int main(void){ for(int i = 1 ; i <= 12 ; i ++){ day[i] += day[i - 1] ;
} int n , m , k ; scanf("%d%d%d" , &n , &m , &k) ; for(int i = 1 ; i <= n ; i ++
){ int mi , di , vi ; scanf("%d%d%d" , &mi , &di , &vi) ; cost[i] = {get(mi , di
) , vi} ; } sort(cost + 1 , cost + 1 + n) ; int cnt = 1 ; f[0][0] = 1 ; for(int
i= 1 ; i <= 365 ; i ++){ for(int j = 0 ; j < M ; j ++) f[i][j] |= f[i - 1][j] ;
while(cnt <= n && cost[cnt].x == i){ for(int j = 0 ; j < M ; j ++){ if(i >= k &&
j>= cost[cnt].y) f[i][j] |= f[i - k][j - cost[cnt].y] ; else if(i < k && j ==
cost[cnt].y){ f[i][j] |= true ; } } ++ cnt ; } } int Min = Inf ; int ans ; for(
int i = M - 1 ; i >= 0 ; i --) if(f[365][i] && abs(i - m) < Min){ Min = abs(i -
m) ; ans = i ; } printf("%d" , ans) ; return 0 ; }
test questions G

There may be a problem with the description of this problem , I redefine the new description ( Just for my understanding ), First, the first line should indicate that if a fault occurs i i i The probability of p i pi pi
, Then each line and column agree with the topic .

Then our problem should be a problem of conditional probability , First of all, we have to figure out all the conditions that will cause failure , Then divide by the conditional probability .

First, we figure out if a Failure , And the probability of only appearing in the third column is
0.3 ∗ 1 ∗ 0.5 ∗ 0.33 ∗ 0.75 ∗ 1.0 0.3 * 1 * 0.5 * 0.33 * 0.75 * 1.0 0.3∗1∗0.5∗
0.33∗0.75∗1.0
All but the third column are 1 − p i 1 - pi 1−pi
The remaining lines are consistent
Note that if there is no direct output result , Otherwise, floating point errors will occur

The code is as follows
#include <iostream> #include <cstring> #include <cmath> #include <algorithm> #
define x first #define y second using namespace std ; typedef pair<long double ,
int> PII ; const int N = 50 + 10 ; const double eps = 1e-8 ; int pi[N] ; int pij
[N][N] ; long double ans[N] ; bool st[N] ; PII tt[N] ; bool cmp(PII a , PII b){
if(fabs(a.x - b.x) > eps) return a.x > b.x ; return a.y < b.y ; } int main(void)
{ // double a = 0.3 * 0.33 * 0.5 * 0.75; // double b = 0.2 * 0.35 * 0.7 ; //
cout << a << " " << b << endl ; // cout << b / (a + b) << endl ; int n , m ;
scanf("%d%d" , &n , &m) ; for(int i = 1 ; i <= n ; i ++) scanf("%d" , &pi[i]) ;
for(int i = 1 ; i <= n ; i ++) for(int j = 1 ; j <= m ; j ++) scanf("%d" , &pij[
i][j]) ; int k ; scanf("%d" , &k) ; for(int i = 1 ; i <= k ; i ++){ int x ;
scanf("%d" , &x) ; st[x] = true ; } for(int i = 1 ; i <= n ; i ++){ ans[i] = 1 ;
for(int j = 1 ; j <= m ; j ++) if(st[j]) ans[i] = ans[i] * pij[i][j] / 100 ;
else ans[i] = ans[i] * (100 - pij[i][j]) / 100 ; ans[i] = ans[i] * pi[i] / 100 ;
} double tot = 0 ; for(int i = 1 ; i <= n ; i ++) tot += ans[i] ; if(fabs(tot) <
eps){ for(int i = 1 ; i <= n ; i ++){ printf("%d 0.00\n" , i) ; } return 0 ; }
for(int i = 1 ; i <= n ; i ++) ans[i] = ans[i] * 100 / tot ; for(int i = 1 ; i
<= n ; i ++) tt[i] = {ans[i] , i} ; sort(tt + 1 , tt + 1 + n , cmp) ; for(int i
= 1 ; i <= n ; i ++){ printf("%d %.2Lf\n" , tt[i].y , tt[i].x) ; } return 0 ; }
test questions H

This topic is a bit of a routine , This is a topic similar to the prefix of a tree .
First we assume 1 As root , Then maintain the slave node i Sum of all degrees of the path node to the root . We assume an array g
g [ a ] + g [ b ] − 2 ∗ g [ l c a ( a , b ) ] + d [ l c a ( a , b ) ] g[a] +
g[b] - 2 * g[lca(a , b)] + d[lca(a , b)]g[a]+g[b]−2∗g[lca(a,b)]+d[lca(a,b)]
It should be noted that if the current a = = b a == b a==b We output directly 1 that will do
Maintenance by multiplication lca that will do
The code is as follows
#include <iostream> #include <cstring> #include <cmath> #include <algorithm>
using namespace std; const int N = 1e5 + 10 ; const int K = 20 ; const int M = 2
* N ; int f[N][K] ; int sz[N] ; int h[N] , e[M] , ne[M] , idx ; long long g[N] ;
int dep[N] ; int d[N] ; void add(int a , int b){ e[idx] = b , ne[idx] = h[a] , h
[a] = idx ++ ; } int lca(int a , int b){ if(dep[a] < dep[b]) swap(a , b) ; for(
int k = K - 1 ; k >= 0 ; k --) if(dep[f[a][k]] >= dep[b]){ a = f[a][k] ; } if(a
== b) { return a ; } for(int k = K - 1 ; k >= 0 ; k --) if(f[a][k] != f[b][k]){
a= f[a][k] ; b = f[b][k] ; } return f[a][0] ; } void dfs(int u , int v){ sz[u] =
1 ; dep[u] = dep[v] + 1 ; g[u] = d[u] + g[v] ; for(int i = h[u] ; ~i ; i = ne[i]
){ int j = e[i] ; if(j == v) continue ; f[j][0] = u ; for(int k = 1 ; k < K ; k
++) f[j][k] = f[f[j][k - 1]][k - 1] ; dfs(j , u) ; } } int main(){ memset(h , -1
, sizeof h) ; int n , m ; scanf("%d%d" , &n , &m) ; for(int i = 1 ; i < n ; i ++
){ int a , b ; scanf("%d%d" ,&a , &b) ; add(a , b) ; add(b , a) ; d[a] ++ , d[b]
++ ; } dfs(1 , 1) ; for(int i = 1 ; i <= m ; i ++){ int a , b; scanf("%d%d" , &a
, &b) ; int c = lca(a , b) ; if(a != b) printf("%lld\n" , g[a] + g[b] - 2 * g[c]
+ d[c]) ; else printf("1\n") ; } return 0 ; }
test questions i

This is a question that is more routine .
In fact, most of the students after observing the topic , It should be possible to find the rule when the ratio of the final speed must be the first term / Last item
Why?
First, let's look at the example , The example is
2 3 3 4 - * - * - * = 2 3 3 4 1
We can also convert to , Eliminate section i Denominator and i + 1 Molecule of , Then the last item after elimination / Last item
The problem is to find two numbers , Can the quotient of their number make up the number we inquire about
The routine of this problem thought of the nature of using sieve method , The sieving method itself is the sieving of a number and a factor of a number .
And the screen method also has a very excellent time complexity of O ( n l o g n ) O(nlogn) O(nlogn)
So the sieving method came out , The solution to this problem is
void init(){ for(int i = 1 ; i < N ; i ++){ if(Hash[i]){ for(int j = i ; j < N
; j += i) if(Hash[j]) ans[j / i] = true ; } } }
The code is as follows
#include <iostream> #include <cstring> #include <cmath> #include <algorithm>
using namespace std; const int N = 2e5 + 10 ; bool Hash[N] ; bool ans[N] ; void
init(){ for(int i = 1 ; i < N ; i ++){ if(Hash[i]){ for(int j = i ; j < N ; j +=
i) if(Hash[j]) ans[j / i] = true ; } } } int main(void){ int n , m ; scanf(
"%d%d" ,&n , &m) ; for(int i = 1 ; i <= n ; i ++){ int x ; scanf("%d" , &x) ;
Hash[x] = true ; } init() ; for(int i = 1 ; i <= m ; i ++){ int x ; scanf("%d" ,
&x) ; if(ans[x]) puts("YES") ; else puts("NO") ; } return 0 ; }
test questions J

This problem is also an obscure knapsack dp
First, let's look at the topic , If we are the most valuable , We must put the small value first , And the same value .
First, let's push the formula
i Represents the front part ,j Indicates the following part
wi + si <= vj wj + si <= vi
It's hard for us to find rules
Switch
wi - vj <= si wj - vi <= si
We can see , Two adjacent wi - vj The smaller the value of, the better . So rewrite cmp
bool cmp(PII a , PII b){ int t = a.x - b.y ; int t1 = b.x - a.y ; return t < t1
; }
And then when we're in order , We can clearly see that this is a naked Backpack dp, And then we directly dp that will do .
The title requires that the current value must be greater than the total weight , We can add a judgment to the state transition .

f [ i ] [ j ] = f [ i − 1 ] [ j ] ; f[i][j] = f[i - 1][j] ; f[i][j]=f[i−1][j];
i f ( j > = w   a n d   v > = j − w ) if(j >= w\ and\ v >= j - w) if(j>=w and
v>=j−w)
f [ i ] [ j ] = m a x ( f [ i ] [ j ] , f [ i − 1 ] [ j − w ] + v ) ; f[i][j]
= max(f[i][j] , f[i - 1][j - w] + v) ;f[i][j]=max(f[i][j],f[i−1][j−w]+v);

The final code is as follows
#include <iostream> #include <cstring> #include <cmath> #include <algorithm> #
define x first #define y second using namespace std ; const int N = 1010 ; const
int M = 2e4 + 10 ; typedef pair<int , int> PII ; int f[N][M] ; PII cost[N] ;
bool cmp(PII a , PII b){ int t = a.x - b.y ; int t1 = b.x - a.y ; return t < t1
; } int main(){ int n ; scanf("%d" , &n) ; for(int i = 1 ; i <= n ; i ++){ int a
, b ; scanf("%d%d" , &a , &b) ; cost[i] = {a , b} ; } sort(cost + 1 , cost + 1 +
n, cmp) ; for(int i = 1 ; i <= n ; i ++){ int w = cost[i].x ; int v = cost[i].y
; for(int j = 0 ; j < M ; j ++){ f[i][j] = f[i - 1][j] ; if(j >= w && v >= j - w
){ f[i][j] = max(f[i][j] , f[i - 1][j - w] + v) ; } } } int ans = 0 ; for(int i
= 0 ; i < M ; i ++) ans = max(ans , f[n][i]) ; printf("%d" , ans) ; return 0 ; }

Technology
Daily Recommendation