Description
Amr bought a new video game "Guess Your Way Out!". The goal of the game is to find an exit from the maze that looks like a perfect binary tree of height h. The player is initially standing at the root of the tree and the exit from the tree is located at some leaf node.
Let's index all the leaf nodes from the left to the right from 1 to 2h. The exit is located at some node n where 1 ≤ n ≤ 2h, the player doesn't know where the exit is so he has to guess his way out!
Amr follows simple algorithm to choose the path. Let's consider infinite command string "LRLRLRLRL..." (consisting of alternating characters 'L' and 'R'). Amr sequentially executes the characters of the string using following rules:
- Character 'L' means "go to the left child of the current node";
- Character 'R' means "go to the right child of the current node";
- If the destination node is already visited, Amr skips current command, otherwise he moves to the destination node;
- If Amr skipped two consecutive commands, he goes back to the parent of the current node before executing next command;
- If he reached a leaf node that is not the exit, he returns to the parent of the current node;
- If he reaches an exit, the game is finished.
Now Amr wonders, if he follows this algorithm, how many nodes he is going to visit before reaching the exit?
Input
Input consists of two integers h, n (1 ≤ h ≤ 50, 1 ≤ n ≤ 2h).
Output
Output a single integer representing the number of nodes (excluding the exit node) Amr is going to visit before reaching the exit by following this algorithm.
Sample Input
1 2
2
2 3
5
3 6
10
10 1024
2046
这道题厉害(把今天做比赛的小牛全部吓跑了||-_-),实际上就是道数学题。
首先把当前他给的出口转换为完全二叉树上的叶子节点标号exit,然后你就可以O(50)的复杂度内求出exit的所有祖先ans[] ;
然后你可以设path[],表示当前这个点是他父亲的左儿子(0),还是右儿子(1)。
通过观察你可以得到这个结论,如果path[i] != path[i-1] ,那么你就把i-1的另一个儿子产生的那颗子树上的节点全部加上,
反之的话这次只要加以。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll ; 4 ll ans[100] ; 5 bool path[100] ; 6 ll h , n ; 7 ll tot ; 8 9 void solve () { 10 //cout << "n = " << n << endl ; 11 //cout << "h = " << h << endl ; 12 ans[h] = n ; 13 for (int i = h - 1 ; i >= 1 ; i --) ans[i] = ans[i+1]/2 ; 14 if (ans[2] == 2) path[2] = 1 , tot += 2; 15 else path[2] = 0 , tot += (1ll<<(h-1)) + 1 ; 16 //printf ("ans[2] = %I64d , path[2] = %d " , ans[2] , path[2]) ; 17 //cout << tot << endl ; 18 for (int i = 3 ; i <= h ; i ++) { 19 if (ans[i-1] * 2 + 1 == ans[i]) path[i] = 0 ; 20 else path[i] = 1 ; 21 tot ++ ; 22 if (path[i] == path[i-1]) tot += (1ll<<(h-i+1)) - 1 ; 23 //printf ("ans = %I64d , path[%d] = %d " , ans[i] , i , path[i]) ; 24 //cout << tot << endl ; 25 } 26 cout << tot - 1 << endl ; 27 } 28 29 int main () { 30 cin >> h >> n ; 31 if (h == 1 && n == 1) { 32 cout << 1 << endl ; 33 return 0 ; 34 } 35 n += (1ll<<h) - 1 ; 36 h ++ ; 37 solve () ; 38 return 0 ; 39 }
Description
Andrewid the Android is a galaxy-famous detective. He is now investigating the case of vandalism at the exhibition of contemporary art.
The main exhibit is a construction of n matryoshka dolls that can be nested one into another. The matryoshka dolls are numbered from 1to n. A matryoshka with a smaller number can be nested in a matryoshka with a higher number, two matryoshkas can not be directly nested in the same doll, but there may be chain nestings, for example, 1 → 2 → 4 → 5.
In one second, you can perform one of the two following operations:
- Having a matryoshka a that isn't nested in any other matryoshka and a matryoshka b, such that b doesn't contain any other matryoshka and is not nested in any other matryoshka, you may put a in b;
- Having a matryoshka a directly contained in matryoshka b, such that b is not nested in any other matryoshka, you may get a out ofb.
According to the modern aesthetic norms the matryoshka dolls on display were assembled in a specific configuration, i.e. as several separate chains of nested matryoshkas, but the criminal, following the mysterious plan, took out all the dolls and assembled them into a single large chain (1 → 2 → ... → n). In order to continue the investigation Andrewid needs to know in what minimum time it is possible to perform this action.
Input
The first line contains integers n (1 ≤ n ≤ 105) and k (1 ≤ k ≤ 105) — the number of matryoshkas and matryoshka chains in the initial configuration.
The next k lines contain the descriptions of the chains: the i-th line first contains number mi (1 ≤ mi ≤ n), and then mi numbersai1, ai2, ..., aimi — the numbers of matryoshkas in the chain (matryoshka ai1 is nested into matryoshka ai2, that is nested into matryoshka ai3, and so on till the matryoshka aimi that isn't nested into any other matryoshka).
It is guaranteed that m1 + m2 + ... + mk = n, the numbers of matryoshkas in all the chains are distinct, in each chain the numbers of matryoshkas follow in the ascending order.
Output
In the single line print the minimum number of seconds needed to assemble one large chain from the initial configuration.
Sample Input
3 2
2 1 2
1 3
1
7 3
3 1 3 7
2 2 5
2 4 6
10
这道题乱入进来的,就是个模拟。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll ; 4 const int M = 1e5 + 10 ; 5 int n , k ; 6 ll tot ; 7 ll len ; 8 int path[M] ; 9 ll cnt ; 10 11 int main () { 12 ios::sync_with_stdio (false) ; 13 cin >> n >> k ; 14 tot = n-1 - (k-1) ; 15 for (int i = 0 ; i < k ; i ++) { 16 int num ; 17 cin >> num ; 18 for (int i = 0 ; i < num ; i ++) cin >> path[i] ; 19 if (path[0] = 1) { 20 for (int i = 1 ; i < num ; i ++) { 21 if (path[i] == path[i-1] + 1) cnt ++ ; 22 else break ; 23 } 24 } 25 } 26 tot -= cnt ; 27 tot += n - 1 - cnt ; 28 cout << tot << endl ; 29 return 0 ; 30 }
虽然一开始就知道是dp,但我没有正确的确定当前的要转移的状态是什么。
题解里说dp[i],表示只用前i种颜色的所有组合情况,那就很明显了,dp[i] = dp[i-1]*C(c[i]-1,pre[i]-1) ;
用了组合数学的姿势,第一次写这种玩意,借鉴了一下大牛的打表姿势。
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll ; 4 const ll mod = 1e9 + 7 ; 5 int k ; 6 int a[2000] ; 7 ll f[2000] ; 8 ll pre[2000] ; 9 ll c[1010][1010] ; 10 11 int main () { 12 ios::sync_with_stdio (false) ; 13 cin >> k ; 14 for (int i = 1 ; i <= k ; i ++) { 15 cin >> a[i] ; 16 pre[i] += pre[i-1] + a[i] ; 17 } 18 for (int i = 0 ; i <= 1000 ; i ++) { 19 c[i][0] = 1 ; 20 for (int j = 1 ; j <= i ; j ++) c[i][j] = (c[i-1][j] + c[i-1][j-1]) % mod ; 21 } 22 f[1] = 1 ; 23 for (int i = 2 ; i <= k ; i ++) { 24 f[i] = f[i-1]*c[pre[i]-1][a[i]-1] % mod ; 25 //printf ("(%I64d , %d) " , pre[i]-1 , a[i]-1) ; 26 //cout << "f[" << i << "] = " << f[i] << endl ; 27 } 28 cout << f[k] << endl ; 29 return 0 ; 30 }