T1 Code spirit mouse \text{T1 code spirit mouse} T1 Code spirit mouse
Description \text{Description} Description
For sequence a a a:
-
a 0 = 1 a_0 = 1 a0=1
-
a n = a i + a j ( n ≥ 1 , i , j a_n = a_i + a_j(n\ge1,i,j an = ai + aj (n ≥ 1,i,j are all in [ 0 , n − 1 ] [0,n-1] Uniform random in [0,n − 1] ) ) )
Request for a given n n n, a n a_n What are your expectations.
- 0 ≤ n ≤ 2147483647 0\le n\le2147483647 0≤n≤2147483647.
Solution \text{Solution} Solution
You calculate the first three items:
a 0 = 1 a_0=1 a0=1
a 1 = ( a 0 + a 0 ) ÷ 1 = 2 a_1=(a_0+a_0)\div1=2 a1=(a0+a0)÷1=2
a 2 = [ ( a 0 + a 0 ) + ( a 0 + a 1 ) + ( a 1 + a 0 ) + ( a 1 + a 1 ) ] ÷ 4 = 3 a_2=[(a_0+a_0)+(a_0+a_1)+(a_1+a_0)+(a_1+a_1)]\div4=3 a2=[(a0+a0)+(a0+a1)+(a1+a0)+(a1+a1)]÷4=3
So you guess a n = n + 1 a_n=n+1 an=n+1.
Then you're right(
Now let's prove it by mathematical induction (the process may be lax, please forgive me):
When n = 0 n=0 When n=0, a 0 = 1 a_0=1 a0 = 1, established.
When ∀ i ∈ [ 0 , n − 1 ] , a i − 1 = i \forall i\in[0,n-1],a_{i-1}=i ∀ i ∈ [0,n − 1], when AI − 1 = i, let E ( x ) E(x) E(x) is x x We have the expectation of x
a n = E ( a i + a J ) ( ∀ i , j ∈ [ 0 , n − 1 ] ) = E ( a i ) + E ( a j ) ( ∀ i , j ∈ [ 0 , n − 1 ] ) = 2 × E ( a i ) ( ∀ i ∈ [ 0 , n − 1 ] ) = 2 × ∑ i = 0 n − 1 a i n = 2 × 1 + 2 + ⋯ + n 2 n = n + 1 \begin{aligned}a_n&=E(a_i+a_J)(\forall i,j\in[0,n-1])\\&=E(a_i)+E(a_j)(\forall i,j\in[0,n-1])\\&=2\times E(a_i)(\forall i\in[0,n-1])\\&=2\times\dfrac{\sum_{i=0}^{n-1}a_i}{n}\\&=2\times\dfrac{\dfrac{1+2+\cdots+n}{2}}{n}\\&=n+1\end{aligned} an=E(ai+aJ)(∀i,j∈[0,n−1])=E(ai)+E(aj)(∀i,j∈[0,n−1])=2×E(ai)(∀i∈[0,n−1])=2×n∑i=0n−1ai=2×n21+2+⋯+n=n+1
Finish the certificate.
Remember the special judgment n = 2147483647 n=2147483647 n=2147483647, n + 1 n+1 n+1 burst int (or it will be lost) 30 30 30 points).
Time complexity O ( T ) \mathcal{O}(T) O(T).
Code \text{Code} Code
#include <iostream> #include <cstdio> using namespace std; int main() { int t; scanf("%d", &t); while (t--) { int n; scanf("%d", &n); if (n == 2147483647) { puts("2147483648"); } else { printf("%d\n", n + 1); } } return 0; }
T2 So many prefix? \text{T2 So many prefix?} T2 So many prefix?
Description \text{Description} Description
Given a string S S S. Request all even length S S S prefix in S S The number and number of occurrences in S.
- about 30 % 30\% 30% of the data, ∣ S ∣ ≤ 100 |S|\le100 ∣ S ∣ ≤ 100 to ensure random data;
- about 100 % 100\% 100% data, ∣ S ∣ ≤ 200000 |S|\le200000 ∣S∣≤200000.
Solution \text{Solution} Solution
provide 2 2 2 ideas, please consult for the remaining one xhj:
1. A C 1. \rm{AC} 1.AC automata + + +Topology mapping optimization
If you only consider even numbers, it's the same as LUOGU5357 [template] AC automata (secondary enhanced version) Almost.
For even bits p o s pos pos is marked, and then search \operatorname{search} When search ing, it keeps jumping when it meets a marked one f a i l fail fail also uses ans + +.
The time complexity of this is O ( ∣ S ∣ 2 ) \mathcal{O}(|S|^2) O(∣ S ∣ 2).
Then add a topology mapping optimization.
Time complexity O ( ∣ S ∣ ) \mathcal{O}(|S|) O(∣S∣).
2. K M P + D P 2. \rm{KMP+\rm{DP}} 2.KMP+DP
set up d p i dp_i dpi = length i i The answer to the prefix of i.
Well, obviously d p i = { d p n x t i + 1 i ≡ 0 ( m o d 2 ) d p n x t i i ≡ 1 ( m o d 2 ) dp_i=\begin{cases}dp_{nxt_i}+1&i\equiv0\pmod{2}\\dp_{nxt_i}&i\equiv1\pmod{2}\end{cases} dpi={dpnxti+1dpnxtii≡0(mod2)i≡1(mod2)
therefore for \operatorname{for} for once, you can push and sum.
Time complexity O ( ∣ S ∣ ) \mathcal{O}(|S|) O(∣S∣).
Code \text{Code} Code
1. 1. 1.
#include <iostream> #include <cstdio> #include <cstring> #include <queue> using namespace std; const int MAXN = 2e5 + 5; int len, tot, cnt; int trie[MAXN][26], id[MAXN], fail[MAXN], head[MAXN], siz[MAXN]; struct edge { int to, nxt; }e[MAXN]; void add(int u, int v) { e[++cnt] = edge{v, head[u]}; head[u] = cnt; } void insert(char *s) { int pos = 0; for (int i = 0; i < len; i++) { int c = s[i] - 'a'; if (!trie[pos][c]) { trie[pos][c] = ++tot; } pos = trie[pos][c]; if (i & 1) { id[(i + 1) >> 1] = pos; } } } void build() { queue<int> q; for (int c = 0; c < 26; c++) { if (trie[0][c]) { q.push(trie[0][c]); } } while (!q.empty()) { int u = q.front(); q.pop(); for (int c = 0; c < 26; c++) { int v = trie[u][c]; if (v) { fail[v] = trie[fail[u]][c]; q.push(v); } else { trie[u][c] = trie[fail[u]][c]; } } } } void search(char *s) { int pos = 0, res = 0; for (int i = 0; i < len; i++) { int c = s[i] - 'a'; pos = trie[pos][c]; siz[pos]++; } for (int i = 1; i <= tot; i++) { add(fail[i], i); } } void dfs(int u) { for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; dfs(v); siz[u] += siz[v]; } } char s[MAXN]; int main() { scanf("%s", s); len = strlen(s); insert(s); build(); search(s); dfs(0); int ans = 0; for (int i = 1; i <= (len >> 1); i++) { ans += siz[id[i]]; //Sum only even numbers } printf("%d\n", ans); return 0; }
2. 2. 2.
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int MAXN = 2e5 + 5; char s[MAXN]; int nxt[MAXN], dp[MAXN]; int main() { scanf("%s", s + 1); int len = strlen(s + 1); for (int i = 2, j = 0; i <= len; i++) { while (j && s[i] != s[j + 1]) { j = nxt[j]; } if (s[i] == s[j + 1]) { j++; } nxt[i] = j; } int ans = 0; for (int i = 1; i <= len; i++) { dp[i] = dp[nxt[i]] + !(i & 1); ans += dp[i]; } printf("%d\n", ans); return 0; }
T3 TRAVEL \text{T3 TRAVEL} T3 TRAVEL
Description \text{Description} Description
On an undirected graph N N N points and M M M edges, each connecting a point a a a and points b b b. There are countless people numbered 1 , 2 , ... , + ∞ 1,2,\dots,+\infty 1,2,..., + ∞. There are certain conditions for passing through an edge. For each edge, there are two values l l l and r r r. Indicates that the edge can only be numbered in [ l , r ] [l,r] [l,r] people in the interval pass through, from 1 1 Arrival at point 1 N N Point N, request the maximum number of people who can pass, and find the number of these people (if there are multiple groups, solve the group with the smallest dictionary order)
- There may be double edges and self rings.
- If no one can pass, just output 0.
- about 30 % 30\% 30% of the data, 1 ≤ N , M ≤ 10 1\le N,M\le10 1≤N,M≤10;
- about 100 % 100\% 100% data, 2 ≤ N ≤ 1000 , 0 ≤ M ≤ 3000 , 1 ≤ a , b ≤ N , 1 ≤ l ≤ r ≤ 1 0 6 2\le N\le1000,0\le M\le3000,1\le a,b\le N,1\le l\le r\le10^6 2≤N≤1000,0≤M≤3000,1≤a,b≤N,1≤l≤r≤106.
Solution \text{Solution} Solution
There are still two ideas (pay attention to the judgment of the smallest dictionary order):
1. 1. 1. Longest road
Traverse each edge, for i i i edge, select edge weight ≥ l i \ge l_i ≥ li edge, from 1 1 1 to N N N run the longest way, let r r r max, at l l l when fixed, it must be r r The bigger the r, the better.
Time complexity O ( M ⋅ M log N ) = O ( M 2 log N ) \mathcal{O}(M\cdot M\log N)=\mathcal{O}(M^2\log N) O(M⋅MlogN)=O(M2logN).
2. 2. 2. Consolidation
It also traverses each edge i i i. Will all meet l j ≤ l i l_j\le l_i lj ≤ li + j j j. All a j a_j aj. And b j b_j bj# merge into a set.
So the final l l l it must be l i l_i li, so put all the r i r_i ri , take one min \min min as final r r r. When point 1 1 1 and point N N N in the same set indicates that you can try to update the answer.
Because it is a joint search set implementation, it can be achieved by combining path compression and rank merging O ( M 2 α ( N ) ) \mathcal{O}(M^2\alpha(N)) O(M2 α (N)) but because N ≤ 1000 N\le1000 N ≤ 1000, so the optimization is not large. The main optimization lies in the constant(
Time complexity O ( M 2 α ( N ) ) \mathcal{O}(M^2\alpha(N)) O(M2α(N)).
Code \text{Code} Code
1. 1. 1.
#include <iostream> #include <cstdio> #include <queue> #include <cstring> using namespace std; const int MAXN = 1005; const int MAXM = 3005; const int INF = 0x3f3f3f3f; int cnt; int head[MAXN]; struct edge { int to, l, r, nxt; }e[MAXM << 1]; void add(int u, int v, int l, int r) { e[++cnt] = edge{v, l, r, head[u]}; head[u] = cnt; } int dis[MAXN]; bool vis[MAXN]; struct node { int u, r; bool operator <(const node &x)const { if (x.r == r) { return x.u < u; } return x.r > r; } }; void init() { memset(dis, -INF, sizeof(dis)); memset(vis, false, sizeof(vis)); } void dijkstra(int l) { init(); dis[1] = INF; priority_queue<node> pq; pq.push(node{1, dis[1]}); while (!pq.empty()) { int u = pq.top().u; pq.pop(); if (vis[u]) { continue; } vis[u] = true; for (int i = head[u]; i; i = e[i].nxt) { if (e[i].l > l) //Taken in the interval { continue; } int v = e[i].to; if (dis[v] < min(dis[u], e[i].r)) //r is taken as min { dis[v] = min(dis[u], e[i].r); pq.push(node{v, dis[v]}); } } } } int l[MAXM], r[MAXM]; int main() { int n, m; scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { int u, v; scanf("%d%d%d%d", &u, &v, l + i, r + i); add(u, v, l[i], r[i]); add(v, u, l[i], r[i]); } int ansk = 0, ansl = 0, ansr = 0; for (int i = 1; i <= m; i++) { dijkstra(l[i]); int res = dis[n] - l[i] + 1; if (ansk < res || (ansk == res && ansl > l[i])) { ansk = res; ansl = l[i]; ansr = dis[n]; } } if (ansk) { printf("%d\n", ansk); for (int i = ansl; i <= ansr; i++) { printf("%d ", i); } } else { puts("0"); } return 0; }
2. 2. 2.
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; const int MAXN = 1005; const int MAXM = 3005; const int INF = 0x3f3f3f3f; struct edge { int u, v, l, r; }e[MAXM]; bool cmp(edge x, edge y) { if (x.r == y.r) { return x.l < y.l; } return x.r > y.r; } int n, m, r, ansk, ansl, ansr; int fa[MAXN], siz[MAXN]; void init() { for (int i = 1; i <= n; i++) { fa[i] = i; siz[i] = 1; } } int find(int x) { if (x == fa[x]) { return x; } return fa[x] = find(fa[x]); //Path compression } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) { scanf("%d%d%d%d", &e[i].u, &e[i].v, &e[i].l, &e[i].r); } sort(e + 1, e + m + 1, cmp); for (int i = 1; i <= m; i++) { init(); r = INF; for (int j = 1; j <= m; j++) { if (e[j].l <= e[i].l) { int x = find(e[j].u), y = find(e[j].v); if (x != y) { if (siz[x] > siz[y]) //Merge by rank { fa[y] = x; siz[x] += siz[y]; } else { fa[x] = y; siz[y] += siz[x]; } r = min(r, e[j].r); if (find(1) == find(n)) { break; } } } } if (find(1) == find(n) && (ansk < r - e[i].l + 1 || (ansk == r - e[i].l + 1 && ansl > e[i].l))) { ansk = r - e[i].l + 1; ansl = e[i].l; ansr = r; } } if (ansk) { printf("%d\n", ansk); for (int i = ansl; i <= ansr; i++) { printf("%d ", i); } } else { puts("0"); } return 0; }
T4 Sneak operation \text{T4 sneak action} T4 Sneak operation
Description \text{Description} Description
LUOGU4516 [JSOI2018] stealth operation
There is one n n n nodes n − 1 n−1 n − 1-sided tree, if at node u u If a monitoring device is installed on u, J can monitor and u u u directly adjacent to all nodes. Pay special attention to the nodes u u u's monitoring device does not monitor u u u itself. There are altogether k k k monitoring devices, requesting how many different methods to place monitoring devices can make all nodes in the tree be monitored.
-
Each node can only install one monitoring device at most, and the monitoring devices must be used up.
-
Output answer m o d 1000000007 \mod1000000007 The remainder of mod1000000007.
-
existence 10 % 10\% 10% of the data, 1 ≤ n ≤ 20 1\le n\le20 1≤n≤20;
-
There is another 10 % 10\% 10% of the data, 1 ≤ n ≤ 100 1\le n\le100 1≤n≤100;
-
There is another 10 % 10\% 10% of the data, 1 ≤ k ≤ 10 1\le k\le10 1≤k≤10;
-
There is another 10 % 10\% 10% of the data, the input tree is guaranteed to be a chain;
-
For all data, 1 ≤ n ≤ 105 1\le n\le105 1≤n≤105, 1 ≤ k ≤ min { n , 100 } 1\le k\le \min\{n,100\} 1≤k≤min{n,100} .
Solution \text{Solution} Solution
This kind of question is at first glance D P \rm DP DP.
set up d p u , x , 0 / 1 , 0 / 1 dp_{u,x,0/1,0/1} dpu,x,0/1,0/1 + u u There are in the subtree of u x x x monitoring devices and nodes u u u whether the monitoring device and node are installed u u Whether u is monitored.
Then push the persimmon (omitting the process below) v v v is u u u's son.
d p u , j + l , 0 , 0 = d p u , j , 0 , 0 × d p v , l , 0 , 1 dp_{u,j+l,0,0}=dp_{u,j,0,0}\times dp_{v,l,0,1} dpu,j+l,0,0=dpu,j,0,0×dpv,l,0,1
d p u , j + l , 0 , 1 = d p u , j , 0 , 1 × ( d p v , l , 0 , 1 + d p v , l , 1 , 1 ) + d p u , j , 0 , 0 × d p v , l , 1 , 1 dp_{u,j+l,0,1}=dp_{u,j,0,1}\times(dp_{v,l,0,1}+dp_{v,l,1,1})+dp_{u,j,0,0}\times dp_{v,l,1,1} dpu,j+l,0,1=dpu,j,0,1×(dpv,l,0,1+dpv,l,1,1)+dpu,j,0,0×dpv,l,1,1
d p u , j + l , 1 , 0 = d p u , j , 1 , 0 × ( d p v , l , 0 , 0 + d p v , l , 0 , 1 ) dp_{u,j+l,1,0}=dp_{u,j,1,0}\times(dp_{v,l,0,0}+dp_{v,l,0,1}) dpu,j+l,1,0=dpu,j,1,0×(dpv,l,0,0+dpv,l,0,1)
d p u , j + l , 1 , 1 = d p u , j , 1 , 0 × ( d p v , l , 1 , 0 + d p v , l , 1 , 1 ) + d p u , j , 1 , 1 × ( d p v , l , 0 , 0 + d p v , l , 0 , 1 + d p v , l , 1 , 0 + d p v , l , 1 , 1 ) dp_{u,j+l,1,1}=dp_{u,j,1,0}\times(dp_{v,l,1,0}+dp_{v,l,1,1})+dp_{u,j,1,1}\times(dp_{v,l,0,0}+dp_{v,l,0,1}+dp_{v,l,1,0}+dp_{v,l,1,1}) dpu,j+l,1,1=dpu,j,1,0×(dpv,l,1,0+dpv,l,1,1)+dpu,j,1,1×(dpv,l,0,0+dpv,l,0,1+dpv,l,1,0+dpv,l,1,1)
matters needing attention:
- d p u , j , 0 / 1 , 0 / 1 dp_{u,j,0/1,0/1} dpu,j,0/1,0/1 should be stored in advance, otherwise it will be used for updating d p u , j + l , 0 / 1 , 0 / 1 dp_{u,j+l,0/1,0/1} dpu,j+l,0/1,0/1 are not from the last round.;
- Direct long long meeting M L E \rm MLE MLE. You need to multiply 1LL when calculating.
Code \text{Code} Code
#include <iostream> #include <cstdio> using namespace std; const int MAXN = 1e5 + 5; const int MOD = 1e9 + 7; int n, k, cnt; int head[MAXN], siz[MAXN], dp[MAXN][105][2][2], tmp[105][2][2]; struct edge { int to, nxt; }e[MAXN << 1]; void add(int u, int v) { e[++cnt] = edge{v, head[u]}; head[u] = cnt; } void dfs(int u, int fa) { siz[u] = dp[u][0][0][0] = dp[u][1][1][0] = 1; //initialization for (int i = head[u]; i; i = e[i].nxt) { int v = e[i].to; if (v == fa) { continue; } dfs(v, u); for (int j = 0; j <= min(siz[u], k); j++) { tmp[j][0][0] = dp[u][j][0][0], dp[u][j][0][0] = 0; tmp[j][0][1] = dp[u][j][0][1], dp[u][j][0][1] = 0; tmp[j][1][0] = dp[u][j][1][0], dp[u][j][1][0] = 0; tmp[j][1][1] = dp[u][j][1][1], dp[u][j][1][1] = 0; } for (int j = 0; j <= min(siz[u], k); j++) { for (int l = 0; l <= min(siz[v], k - j); l++) { dp[u][j + l][0][0] = (dp[u][j + l][0][0] + 1LL * tmp[j][0][0] * dp[v][l][0][1] % MOD) % MOD; dp[u][j + l][0][1] = (dp[u][j + l][0][1] + 1LL * tmp[j][0][1] * (1LL * dp[v][l][0][1] + 1LL * dp[v][l][1][1]) % MOD + 1LL * tmp[j][0][0] * dp[v][l][1][1] % MOD) % MOD; dp[u][j + l][1][0] = (dp[u][j + l][1][0] + 1LL * tmp[j][1][0] * (1LL * dp[v][l][0][0] + 1LL * dp[v][l][0][1]) % MOD) % MOD; dp[u][j + l][1][1] = (dp[u][j + l][1][1] + 1LL * tmp[j][1][0] * (1LL * dp[v][l][1][0] + 1LL * dp[v][l][1][1]) % MOD + 1LL * tmp[j][1][1] * (1LL * dp[v][l][0][0] + 1LL * dp[v][l][0][1] + 1LL * dp[v][l][1][0] + 1LL * dp[v][l][1][1]) % MOD) % MOD; } } siz[u] += siz[v]; } } int main() { scanf("%d%d", &n, &k); for (int i = 1; i < n; i++) { int u, v; scanf("%d%d", &u, &v); add(u, v); add(v, u); } dfs(1, 0); printf("%d\n", (dp[1][k][0][1] + dp[1][k][1][1]) % MOD); //Finally, point 1 must be monitored return 0; }