当前位置:网站首页>2022.7.22 simulation match
2022.7.22 simulation match
2022-07-24 13:50:00 【lAWTYl】
T1 tree
First , Thank you, the author /wx

It is required to find out the number of schemes that divide a tree into several connected parts .
First of all, it's easy to think of , Points out the “ subtree ” Size d d d Is to meet d ∣ n d | n d∣n Of . That is to say, we only need to judge each d d d If it is feasible , among d d d The number of is equal to σ 0 ( n ) < n \sigma_0(n) < \sqrt{n} σ0(n)<n Of .
It is quite simple to judge whether it is feasible , You only need to write one d f s dfs dfs Just simulate the process of tree splitting , therefore c h e c k check check Namely O ( n ) O(n) O(n) Of . Then the total complexity is less than O ( n n ) O(n\sqrt{n}) O(nn) Of .
#include<bits/stdc++.h>
using namespace std;
#define in read()
#define MAXN 2002000
#define MAXM MAXN << 2
#define MOD 998244353
inline int read(){
int x = 0; char c = getchar();
while(c < '0' or c > '9') c = getchar();
while('0' <= c and c <= '9'){
x = x * 10 + c - '0'; c = getchar();
}
return x;
}
int n = 0;
int cnt = 0;
int d[MAXN] = {
0 };
int tot = 0;
int first[MAXN] = {
0 };
int nxt[MAXM] = {
0 };
int to[MAXM] = {
0 };
inline void add(int x, int y){
nxt[++tot] = first[x];
first[x] = tot; to[tot] = y;
}
int sz[MAXN] = {
0 };
void prework(int x, int fa){
sz[x]++;
for(int e = first[x]; e; e = nxt[e]){
int y = to[e];
if(y == fa) continue;
prework(y, x);
sz[x] += sz[y];
}
}
int check(int x, int fa, int w){
int siz = 1;
for(int e = first[x]; e; e = nxt[e]){
int y = to[e];
if(y == fa) continue;
if(sz[y] >= w){
// Greater than continue down first
int f = check(y, x, w);
if(f == -1) return -1;
siz += f; // Add the following contributions
}
else siz += sz[y];
if(siz > w) return -1; // All wood is big
}
if(siz == w) return 0; // It's equivalent to cutting directly Not a contribution
return siz;
}
int main(){
// freopen("a.in", "r", stdin);
n = in; int ans = 0;
for(int i = 1; i < n; i++){
int x = in, y = in;
add(x, y), add(y, x);
} prework(1, 0);
for(int i = 1; i * i <= n; i++)
if(n % i == 0) d[++cnt] = i;
for(int i = cnt; i >= 1; i--)
if(n / d[i] != d[i]) d[++cnt] = n / d[i];
// for(int i = 1; i <= cnt; i++) cout << d[i] << ' '; puts("");
for(int i = 1; i <= cnt; i++)
if(check(1, 0, d[i]) != -1) ans = (ans + 1) % MOD;
cout << ans << '\n';
return 0;
}
But this kind of writing seems to T T T fall 2 , 3 2,3 2,3 A little bit , So we have to continue to see if there is any nature .
We consider finding s i z e size size yes d d d The key point of the multiple of ( Because we just looked for these points when simulating tree demolition ). We consider finding the upper limit of these points , We extract these key points , Of leaf nodes in the new tree s i z e size size At least d d d, And non leaf node s i z e size size It must be better than all its sons s i z e size size And to be big , And at least big d d d. So obviously, the upper limit of the number of key points is n d \frac nd dn.
If we happen to find n d \frac nd dn A key point , It means that each point is exactly one with the size of d d d The root of the subtree of , And these subtrees do not contain each other . in other words , If there is n d \frac nd dn A key point , The requirements of the topic can be established . So we can rewrite it through this c h e c k ( ) check() check() Function can A A A 了 .
#include<bits/stdc++.h>
using namespace std;
#define in read()
#define MAXN 1001000
#define MAXM MAXN << 2
inline int read(){
int x = 0; char c = getchar();
while(c < '0' or c > '9') c = getchar();
while('0' <= c and c <= '9'){
x = x * 10 + c - '0'; c = getchar();
}
return x;
}
int n = 0;
int d[MAXN] = {
0 };
int tot = 0;
int first[MAXN] = {
0 };
int nxt[MAXM] = {
0 };
int to[MAXM] = {
0 };
inline void add(int x, int y){
nxt[++tot] = first[x];
first[x] = tot; to[tot] = y;
}
int siz[MAXN] = {
0 };
int cnt[MAXN] = {
0 };
void prework(int x, int fa){
siz[x]++;
for(int e = first[x]; e; e = nxt[e]){
int y = to[e];
if(y == fa) continue;
prework(y, x);
siz[x] += siz[y];
}
cnt[siz[x]]++;
}
bool check(int d){
int num = 0;
for(int i = d; i <= n; i += d)
num += cnt[i];
return num == (n / d);
}
int main(){
n = in; int ans = 0;
for(int i = 1; i < n; i++){
int x = in, y = in;
add(x, y), add(y, x);
} prework(1, 0);
for(int i = 1; i <= n; i++)
if(n % i == 0) ans += check(i);
cout << ans << '\n';
return 0;
}
T2 seq
30 p t s 30pts 30pts It's a simple one d p dp dp. We make f i , j f_{i, j} fi,j Before presentation i i i A digital , And then finally j j j The minimum value of , So there are :
f i , j = min j = a i A { min k = a i − 1 A { f i − 1 , k + c ∣ j − k ∣ + ( a i − j ) 2 } } f_{i, j} = \min_{j = a_i}^A \{\min_{k = a_{i - 1}}^A\{ f_{i - 1, k} + c|j - k| + (a_i - j)^2 \}\} fi,j=j=aiminA{ k=ai−1minA{ fi−1,k+c∣j−k∣+(ai−j)2}}
Initialization is f 1 , j = ( j − a 1 ) 2 j ∈ [ a i , A ] f_{1, j} = (j - a_1)^2 \quad j \in[a_i, A] f1,j=(j−a1)2j∈[ai,A], among A A A yes a i a_i ai Range of values . The time complexity of doing this is O ( n A 2 ) O(nA^2) O(nA2) Of .
#include<bits/stdc++.h>
using namespace std;
#define in read()
#define MAXN 1010
#define INFI 1 << 30
inline int read(){
int x = 0; char c = getchar();
while(c < '0' or c > '9') c = getchar();
while('0' <= c and c <= '9'){
x = x * 10 + c - '0'; c = getchar();
}
return x;
}
int a[MAXN] = {
0 };
int n = 0; int c = 0;
int f[MAXN][MAXN] = {
0 };
int main(){
n = in; c = in; int A = 0, ans = INFI;
for(int i = 1; i <= n; i++) a[i] = in, A = 101;
memset(f, 0x3f, sizeof(f));
for(int j = a[1]; j <= A; j++) f[1][j] = (j - a[1]) * (j - a[1]);
for(int i = 2; i <= n; i++)
for(int j = a[i]; j <= A; j++)
for(int k = a[i - 1]; k <= A; k++)
f[i][j] = min(f[i][j], f[i - 1][k] + c * abs(j - k) + (j - a[i]) * (j - a[i]));
for(int i = 1; i <= A; i++) ans = min(ans, f[n][i]);
cout << ans << '\n';
return 0;
}
We consider optimizing this approach . Let's change the above formula slightly :
f i , j = min j = a i A { min k = a i − 1 A { f i , k + c ∣ j − k ∣ } + ( a i − j ) 2 } f_{i, j} = \min_{j = a_i}^A \{ \min_{k = a_{i - 1}}^A \{ f_{i, k} + c|j - k| \} + (a_i - j)^2 \} fi,j=j=aiminA{ k=ai−1minA{ fi,k+c∣j−k∣}+(ai−j)2}
Then if we order s i , j = min k = a i − 1 A { f i , k + c ∣ j − k ∣ } s_{i, j} = \min\limits_{k = a_{i - 1}}^A \{ f_{i, k} + c|j - k| \} si,j=k=ai−1minA{ fi,k+c∣j−k∣}, And the s i , j s_{i, j} si,j Preprocess it , Then we can enumerate less once A A A, The equation can be written like this :
f i , j = min j = a i A { s i , j + ( a i − j ) 2 } f_{i, j} = \min_{j = a_i}^A \{ s_{i, j} + (a_i - j)^2 \} fi,j=j=aiminA{ si,j+(ai−j)2}
Now let's consider how to preprocess s i , j s_{i, j} si,j. We consider that if we take the absolute value apart, it is good to transfer , That's our s i , j s_{i, j} si,j If it is equal to min k = a i − 1 A { f i , k + c ( j − k ) } \min\limits_{k = a_{i - 1}}^A \{ f_{i, k} + c(j - k) \} k=ai−1minA{ fi,k+c(j−k)} That's a lot easier to deal with , Because we can :
min { f i , k + c ( j − k ) } = min { min { f i , k + c ( j − 1 − k ) } + c , f i − 1 , j } \min \{ f_{i, k} + c(j - k) \} = \min \{ \min \{f_{i, k} + c(j - 1 - k) \} + c, f_{i - 1, j} \} min{ fi,k+c(j−k)}=min{ min{ fi,k+c(j−1−k)}+c,fi−1,j}
in other words :
s i , j = min { s i , j − 1 + c , f i − 1 , j } s_{i, j} = \min \{ s_{i, j - 1} + c, f_{i - 1, j} \} si,j=min{ si,j−1+c,fi−1,j}
But there is an absolute value here , So we'll think about scanning it directly and then scanning it backwards , In this way, the problem of absolute value can be solved ( Note that here we need to use a scrolling array to avoid space explosion ). In this way, the time complexity becomes O ( n A ) O(nA) O(nA) Of course. .
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define in read()
#define MAXN 100100
#define MAXA 101
#define INFI 1e18
inline int read(){
int x = 0; char c = getchar();
while(c < '0' or c > '9') c = getchar();
while('0' <= c and c <= '9'){
x = x * 10 + c - '0'; c = getchar();
}
return x;
}
int a[MAXN] = {
0 };
int n = 0; int c = 0;
int f[MAXN][MAXA] = {
0 };
int g1[MAXN] = {
0 };
int g2[MAXN] = {
0 };
signed main(){
n = in; c = in; int A = 0, ans = INFI;
for(int i = 1; i <= n; i++) a[i] = in, A = max(A, a[i]);
memset(f, 0x3f, sizeof f);
for(int j = a[1]; j <= A; j++) f[1][j] = 1ll * (j - a[1]) * (j - a[1]);
for(int i = 2; i <= n; i++){
for(int j = 0; j <= A + 1; j++) g1[j] = g2[j] = INFI;
for(int j = A; j >= a[i]; j--)
g1[j] = min(g1[j], min(g1[j + 1] + c, f[i - 1][j]));
for(int j = a[i - 1]; j <= A; j++)
g2[j] = min(g2[j], min(g2[j - 1] + c, f[i - 1][j]));
for(int j = a[i]; j <= A; j++)
f[i][j] = min(f[i][j], min(g1[j], g2[j]) + 1ll * (j - a[i]) * (j - a[i]));
}
for(int i = 1; i <= A; i++) ans = min(ans, f[n][i]);
cout << ans << '\n';
return 0;
}
T3 color
Feeling T 3 T3 T3 Is the simplest problem ( It seems that the original T 3 T3 T3 Replaced ).
Brain pumping in the examination room , The idea has been wrong , Push :
a n s = ∑ S ⊂ U ∣ ∑ i ∈ S a i − ∑ i ∈ C U S a i ∣ = ∑ S ⊂ U ∣ 2 ∑ i ∈ S a i − X ∣ X = ∑ i = 1 n a i \begin{aligned} ans = & \sum_{S \subset U} \bigg| \sum_{i \in S}a_i - \sum_{i \in C_US}a_i \bigg| \\ = & \sum_{S \subset U} \bigg| 2\sum_{i \in S}a_i - X \bigg| \\ X = & \sum_{i = 1}^na_i \end{aligned} ans==X=S⊂U∑∣∣i∈S∑ai−i∈CUS∑ai∣∣S⊂U∑∣∣2i∈S∑ai−X∣∣i=1∑nai
It was supposed to be this step , The solution will come out soon , Then I began to get sick :
X = ∑ i = 1 n a i a n s = ∑ S ⊂ U ∣ ∑ i ∈ S a i − ∑ i ∈ C U S a i ∣ = ∑ S ⊂ U ∣ 2 ∑ i ∈ S a i − X ∣ = ∑ S ⊂ U ( 2 ∑ i ∈ S a i − X ) [ 2 ∑ i ∈ S a i ≥ X ] − ∑ S ⊂ U ( 2 ∑ i ∈ S a i − X ) [ 2 ∑ i ∈ S a i < X ] = ( 2 ∑ S ⊂ U ∑ i ∈ S a i − ∑ S ⊂ U X ) [ 2 ∑ i ∈ S a i ≥ X ] − ( 2 ∑ S ⊂ U ∑ i ∈ S a i − ∑ S ⊂ U X ) [ 2 ∑ i ∈ S a i < X ] \begin{aligned} X = & \sum_{i = 1}^na_i \\\\ ans = & \sum_{S \subset U} \bigg| \sum_{i \in S}a_i - \sum_{i \in C_US}a_i \bigg| \\ = & \sum_{S \subset U} \bigg| 2\sum_{i \in S}a_i - X \bigg| \\ = & \sum_{S \subset U}\left( 2\sum_{i \in S}a_i - X \right)[2\sum_{i \in S}a_i \geq X] - \sum_{S\subset U}\left( 2\sum_{i \in S}a_i - X \right)[2\sum_{i \in S}a_i < X] \\\\ = & \left(2\sum_{S \subset U}\sum_{i \in S}a_i - \sum_{S\subset U}X\right)[2\sum_{i \in S}a_i \geq X] - \left(2\sum_{S \subset U}\sum_{i \in S}a_i - \sum_{S\subset U}X\right)[2\sum_{i \in S}a_i < X] \end{aligned} X=ans====i=1∑naiS⊂U∑∣∣i∈S∑ai−i∈CUS∑ai∣∣S⊂U∑∣∣2i∈S∑ai−X∣∣S⊂U∑(2i∈S∑ai−X)[2i∈S∑ai≥X]−S⊂U∑(2i∈S∑ai−X)[2i∈S∑ai<X](2S⊂U∑i∈S∑ai−S⊂U∑X)[2i∈S∑ai≥X]−(2S⊂U∑i∈S∑ai−S⊂U∑X)[2i∈S∑ai<X]
Then I can't push it .
In fact, the above formula can already be done . We make f j f_j fj Represents the selected subset S S S in ∑ i ∈ S a i = j \sum\limits_{i \in S}a_i = j i∈S∑ai=j The number of sets of . So obviously now this is a backpack . We have :
f j = ∑ a k ≤ j f j − a k f_j = \sum_{a_k \leq j}f_{j - a_k} fj=ak≤j∑fj−ak
Just transfer the backpack directly , Complexity is O ( n S ) O(nS) O(nS).
Then the answer is obvious :
a n s = ∑ i = 1 X f i ∣ 2 i − X ∣ ans = \sum_{i = 1}^Xf_i|2i - X| ans=i=1∑Xfi∣2i−X∣
#include<bits/stdc++.h>
using namespace std;
#define in read()
#define MAXN 100100
#define MOD 998244353
inline int read(){
int x = 0; char c = getchar();
while(c < '0' or c > '9') c = getchar();
while('0' <= c and c <= '9'){
x = x * 10 + c - '0'; c = getchar();
}
return x;
}
int T = 0;
int x = 0; int n = 0;
int w[MAXN] = {
0 };
int f[MAXN] = {
0 };
int main(){
T = in;
while(T--){
x = in; n = in; int ans = 0;
f[0] = 1;
for(int i = 1; i <= x; i++) f[i] = 0;
for(int i = 1; i <= n; i++) w[i] = in;
for(int i = 1; i <= n; i++)
for(int j = x; j >= w[i]; j--)
f[j] = (f[j] + f[j - w[i]]) % MOD;
for(int i = 0; i <= x; i++) ans = (ans + 1ll * f[i] * abs(2 * i - x) % MOD) % MOD;
cout << ans << '\n';
}
return 0;
}
T4 mex
It seems that I have done the same problem before …
Portal :P4587 [FJOI2016] Mysterious number
Unfortunately, I didn't remember it in the examination room , There is no time to write .
T J TJ TJ I have written one before , Now move over directly .
Find the number that cannot be represented by the subset with the smallest interval .
Consider an interval [ l , r ] [l, r] [l,r], Sort this paragraph in ascending order , Set the numbers after sorting as a l ≤ a l + 1 ≤ ⋯ ≤ a r a_l \leq a_{l+1} \leq \cdots \leq a_r al≤al+1≤⋯≤ar, For now a l a_l al If not equal to 1 1 1, Then you can output directly 1 1 1. If it is equal to the 1 1 1 Let's consider a simple d p dp dp.
Now use p o s pos pos Indicates that the current number that can be expressed belongs to the interval [ 1 , p o s ] [1, pos] [1,pos]( Obviously, this interval includes 1 1 1), For the next number a i a_i ai, Now there are two situations :
- If a i ≤ p o s + 1 a_i \leq pos + 1 ai≤pos+1, Then the set of numbers that can be expressed now is [ 1 , p o s ] ⋃ [ 1 + a i , p o s + a i ] = [ 1 , p o s + a i ] [1, pos] \bigcup [1 + a_i, pos + a_i] = [1, pos + a_i] [1,pos]⋃[1+ai,pos+ai]=[1,pos+ai].
- If a i > p o s + 1 a_i> pos + 1 ai>pos+1, Then the set of numbers that can be expressed now is [ 1 , p o s ] ⋃ [ 1 + a i , p o s + a i ] [1, pos] \bigcup [1 + a_i, pos + a_i] [1,pos]⋃[1+ai,pos+ai], Obviously, this set does not contain p o s + 1 pos + 1 pos+1, So the answer is p o s + 1 pos + 1 pos+1.
The time complexity of doing this for each inquiry is O ( n log n ) O(n\log n) O(nlogn) Of , So we should consider optimizing this practice .
If the current value range is [ 1 , p o s ] [1, pos] [1,pos], Now the answer should be p o s + 1 pos + 1 pos+1. Remember that it is less than or equal to a n s ans ans The sum of the numbers is r e s res res, If r e s ≥ a n s res \geq ans res≥ans, Then it means that you must have chosen ( Choose the sum of some numbers as a n s ans ans) And less than or equal to a n s ans ans The number of exists , Now let a n s = r e s + 1 ans = res + 1 ans=res+1. If not satisfied r e s ≥ a n s res \geq ans res≥ans That means the answer is a n s ans ans, direct b r e a k break break Just fine , be aware ∑ a i < 1 e 9 \sum a_i < 1e9 ∑ai<1e9, Therefore, we can consider using the chairman tree to maintain the interval value range and .
#include<bits/stdc++.h>
using namespace std;
#define in read()
#define MAXN 100100
#define INFI 1 << 30
inline int read(){
int x = 0; char c = getchar();
while(c < '0' or c > '9') c = getchar();
while('0' <= c and c <= '9'){
x = x * 10 + c - '0'; c = getchar();
}
return x;
}
int a[MAXN] = {
0 };
int n = 0; int m = 0;
struct Tnode{
int dat;
int ls, rs;
}t[MAXN << 5];
int tot = 0;
int root[MAXN] = {
0 };
inline void up(int p) {
t[p].dat = t[t[p].ls].dat + t[t[p].rs].dat; }
int update(int now, int l, int r, int x, int val){
int p = ++tot; t[p] = t[now];
if(l == r) {
t[p].dat += val; return p; }
int mid = (l + r) >> 1;
if(x <= mid) t[p].ls = update(t[p].ls, l, mid, x, val);
else t[p].rs = update(t[p].rs, mid + 1, r, x, val);
up(p); return p;
}
int query(int p, int q, int l, int r, int ql, int qr){
if(ql <= l and r <= qr) return t[p].dat - t[q].dat;
int mid = (l + r) >> 1, ans = 0;
if(ql <= mid) ans += query(t[p].ls, t[q].ls, l, mid, ql, qr);
if(qr > mid) ans += query(t[p].rs, t[q].rs, mid + 1, r, ql, qr);
return ans;
}
int main(){
n = in;
for(int i = 1; i <= n; i++) a[i] = in;
for(int i = 1; i <= n; i++) root[i] = update(root[i - 1], 1, INFI, a[i], a[i]);
m = in;
while(m--){
int l = in, r = in, ans = 1;
while(true){
int res = query(root[r], root[l - 1], 1, INFI, 1, ans);
if(res >= ans) ans = res + 1;
else break;
}
cout << ans << '\n';
}
return 0;
}
边栏推荐
- uni-app 背景音频 熄屏或者退回桌面之后不在播放
- The latest and complete Flink series tutorials in 2021_ Preliminary exploration of Flink principle and flow batch integration API (II. V) V2
- Adjust the array order so that odd numbers precede even numbers
- Network security - file upload penetration test
- JS execution mechanism
- 网络安全——WAR后门部署
- The gather function of tidyr package of R language converts a wide table into a long table (a wide table into a long table), the first parameter specifies the name of the new data column generated by
- Flinktable & SQL (VII)
- JQ remove an element style
- Common OJ questions of stack and queue
猜你喜欢
随机推荐
Nessus安全测试工具使用教程
The latest and complete Flink series tutorials in 2021_ Preliminary exploration of Flink principle and flow batch integration API (II. V) V2
Happy number ~ ~ ~ (in fact, I'm not happy at all) & ugly number
CSDN垃圾的没有底线!
Network security -- man in the middle attack penetration test
Data type binary string type
网络安全——服务漏洞扫描与利用
uni-app 背景音频 熄屏或者退回桌面之后不在播放
R语言使用epiDisplay包的statStack函数基于因子变量通过分层的方式查看连续变量的统计量(均值、中位数等)以及对应的假设检验、对连续数据进行对数化之后符合参数检验条件自动执行参数检验
Kunyu(坤舆) 安装 详解
Network security - file upload content check bypass
Unity行人随机行走不碰撞
网络安全——过滤绕过注入
Network security - error injection
OWASP ZAP安全测试工具使用教程(高级)
rhcsa第六次笔记
关于不定方程解的个数的问题
How to quickly wrap lines in Excel table
如何在树莓派上搭建运行 WordPress
Difference between code signing certificate and SSL certificate









