HGOI 20191105 problem solution

Problem A Joker

Tiger and garlic are good friends.

Summer is over, cool autumn arrives, tigers and garlic has a new entertainment projects.
Tiger is a distant cousin of the Siberian tiger, there prevailed a card game: two players involved in the game, props is one of 54 playing cards, 52 cards and two basic Joker, also known as ace. These two are the king of red and black. It is divided into 52 basic cards spades, hearts, clubs, square piece four suits, each suit has 13 cards, 13 cards which have a hierarchical order, followed respectively 234 567 8 9 10 JQKA, where 2 is the lowest level, a is the highest rank. All hearts and side pieces are considered to be red, and all the spades and clubs are considered to be black. There is a suit would be hard spot, we call this suit cards to the dealer cards.
Before the start of a game, two players have hands of six cards, and the remaining 42 cards form the deck. A game consisting of several rounds of the game, before the start of each round, two players on hand were a number of cards, a player the upper hand, another player of escape. Just get the number of players should be put on the table the same level of licensing a number of sheets, pay attention to just get the players are not allowed to trump placed at any time, and place the cards can not exceed the total number of cards FLAC players have hands. Players can choose to flip some of his cards were stacked on the first player card, a card can be stacked on another card taken and only if there is at least one of the following conditions are met:
1. This card and the stack of cards the same suit, and has a higher level.
2. This card is the dealer card, the cards are not stacked.
3. This card is a trump card, and the cards and the stack of the same color.
4. This card is a trump card, and it's the same color as the dealer and brand colors.

After all the cards have been stacked on the table, you can then place the upper hand by a number of cards on the table, these cards must be level and any card on the table of the same rank (whether or not the stack), then hand players can still choose some of their own stacks on the first player cards. Note that the first player still can not place more than the number of FLAC player's hand cards on the table.
Round game is over, if and only if one of two things happen: FLAC players can not or do not want to stack cards on the table, or just get a player can not or do not want to put more cards. In the first case, when any of the players that do not have the time to continue to flip it round game, first player still has a chance to continue to place non-trump playing cards, and the cards are placed on the desktop level and still existing a card the same level, and the total number is not on the desktop stack of cards can not exceed the total number of players on hand flip the cards. After that, FLAC player loses this round, and add all the cards on the table their own hands. The next round of the game, the first player and FLAC player's character unchanged.
In the second case, FLAC player wins this round. All cards on the desktop will be removed (not into the deck), while the upper hand in the next round and FLAC player's character will be interchangeable, that becomes first player FLAC player, the player becomes the first player FLAC .
Between the wheel and the wheel, if the first player of the last round of the hand not more than six, he would start a card from the top of the pile start to take a card, until the hand happens to have six or all of the deck cards have been removed.
If before a game begins, a player has no cards in hand, while the other player is still hand, then no player wins the hand of this board game. If two players have no hand, then the Council game ended in a draw. In at least two players have a hand, but the first player's hand only trump card - he can not do any action - under the circumstances, we believe that the Council FLAC players win the game.
Tiger and garlic being such a game, we are given the deck, in the hands of two hands and a special card suit, your goal is to determine who is the winner in the optimal strategy of this game round Yes. Note: Information on the deck for the both open. Siberian tiger is a tiger friend, garlic therefore decided to let each game Tiger upper hand.
Tigers think about the game too complicated, so the Tigers will remove certain grades of cards to start all cards in each game before the game, but to ensure that the remaining tigers at least three levels of cards that have at least 14 cards to make game to proceed smoothly.

Solution : 

  Fortunately, this problem seen almost known in the original title, which is an immortal tourist question.

  Garbage for $ 95 \% $, personally think that this question is of little value.

  As long as no two flip king, then flip to win, or win the upper hand.

  Under optimal strategy, FLAC not only need to have the upper hand and then let the deck touch all over just fine.

  Trick is a problem

#include <bits/stdc++.h>

using namespace std;

const int N = 1005;

string s1, s2, s3, c, level;

int main() {
  int T; cin >> T;
  char ch; cin >> ch;
  while (T--) {
    int flg = 0;
    getline(cin, level);
    getline(cin, s1);
    getline(cin, s2);
    for (int i = 0; i < (int) s2.size(); i++) {
      if (s2[i] == 'R' && s2[i + 1] == 'J') 
        flg++;
      if (s2[i] == 'B' && s2[i + 1] == 'J') 
        flg++;
    }
    getline(cin, s3);
    getline(cin, c);
    if (flg == 2) 
      printf("laohu\n");
    else 
      printf("dasuan\n");
  }
  return 0; 
}
joker.cpp

Problem B swap

Given two n-length $ $ arranged $ a, b $, each operation section may be $ A $ in $ [L, R] $ out, its maximum and minimum switching sequence.

$ $ 345,678 in the operations, will become $ A $ $ b $.

For $ 100 \ $% guarantee of data, $ 1 \ leq n \ leq 4096 $

Solution :

  Before there is a similar problem, still consider merge sort sets of quick sort of thinking.

  If we can sort a $ A $ array, which is a sequence of operations $ S $, $ b $ array will sort, which is a sequence of operations $ T $

  Since then the operation reversible, so we only need positive sequence output of $ S $, then $ T $ to reverse the output.

  Use merge sort, the problem can be transformed into, how to merge two increments ordered sequence.

  This thing, we need to use a divide and conquer approach to complete.

  Set the current interval to be merged $ [l0, r0] $ and $ [l1, r1] $

  

   Is set to be merged segment $ [l0, r0] $, $ [l1, r1] $, to find a minimum length $ pt $, such that $ [r0-pt + 1, r0] $ $ than the magnitude of the number of [l1, l1 + pt-1] $ size large numbers.

  This time, we will need $ [r0-pt + 1, l1 + pt-1] $ interval number ordered, so we do need to turn three $ update $ operation.

  I.e., reversing interval $ [r0, pt + 1, r0] $, inversion interval $ [l1, l1 + pt-1] $, inversion interval $ [r0-pt + 1, l1 + pt-1] $

  In this case the problem into two sub-problems: the $ [l0, l0-pt] $ and $ [r0-pt + 1, r0] $ combination; the $ [l1, l1 + pt-1] $ and $ [L1 + pt, r1] $ combined.

  Such a partition, are each divided into two segments will be, time complexity is $ O (log_2 l) $, where $ $ L represents the length of the line.

  Therefore, a merge sort coat, final time complexity of this problem is $ O (n {log_2} ^ 2 n) $

# include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,a[N];
vector< pair<int,int> >ans[2];
void update(int op,int l,int r) {
    for (int i=0;i<(r-l+1)/2;i++) {
        ans[op].push_back(make_pair(l+i,r-i)),swap(a[l+i],a[r-i]);
    }
}
void merge(int op,int l0,int r0,int l1,int r1) {
    if (l0>r0 || l1>r1) return;
    int l=min(r0-l0,r1-l1),pt=0;
    while (pt<=l) if (a[r0-pt]>=a[l1+pt]) pt++; else break;
    if (!pt) return;
    update(op,r0-pt+1,r0);
    update(op,l1,l1+pt-1);
    update(op,r0-pt+1,l1+pt-1);
    merge(op,l0,r0-pt,r0-pt+1,r0);
    merge(op,l1,l1+pt-1,l1+pt,r1); 
}
void solve(int op,int l,int r) {
    if (l >= r) return;
    int mid = (l+r)>>1;
    solve(op,l,mid); solve(op,mid+1,r);
    merge(op,l,mid,mid+1,r);
}
int main()
{
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    solve(0,1,n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    solve(1,1,n);
    reverse(ans[1].begin(),ans[1].end());
    printf("%d\n",ans[0].size()+ans[1].size());
    for (int i=0;i<ans[0].size();i++) printf("%d %d\n",ans[0][i].first,ans[0][i].second);
    for (int i=0;i<ans[1].size();i++) printf("%d %d\n",ans[1][i].first,ans[1][i].second);
    return 0;
}
swap.cpp

Problem C actor 

你有$m$种颜料,你要按照某个顺序选择颜料,每次在长度为$n$

的墙壁上刷一个区间,墙壁必须刷满,求可能刷出的墙壁方案数。

对于$100\%$的数据满足$1 \leq n\leq 10^6, m \leq 300$

Solution : 

  我们会首先考虑一个$O(mn^2)$的暴力$dp$.

  设$f[i][j][k]$表示当前涂到第$i$个格子,使用了$j$个颜色,而有$k$个颜色一定会在后来的涂色中涂到。

  那么$f[0][0][0] = 1$,采用刷表法转移。

  考虑$f[i][j][k]$可以转移到

  新放一个在之后将不会再刷到这个颜色: $f[i+1][j+1][k]$

  新放一个在之后还会刷到这个颜色:$f[i+1][j+1][k+1]$

  选择一个老颜色放在当前位置,并终结$f[i+1][j][k-1]$,此时要求$k\geq 1$

  选择一个老颜色放在当前位置,并不终结$f[i+1][j][k]$, 此时要求$k\geq 1$

  答案就是$\sum\limits_{i = 1}^{m} ({A_m}^i \times f[n][i][0])$

  我们考虑到,最终的答案必然是由最多$2m$个相同颜色的块组成的,所以第一维状态可以压成和$m$有关系的了。

  如果求出了块数为$i$的方案数$s$,那么可以通过插板法求出原来序列的答案了,即${C_{n-1}}^{i-1} \times s$

  将状态改为$f[i][j][k]$表示当前考虑到$i$块,已经使用$j$个颜色,该块和该块之后最多能放置的已经放过的颜色的数目为$k$。

  那么,$f[i+1][j][k] = f[i][j][k+1]+f[i][j][k+2] + ...$ ,此时只要在第$i+1$放一个已经放过的颜色就能实现。

  若考虑新放置一个$j+1$的颜色,其有$(m-j)$种元素好挑,所以转移方程为$f[i+1][j+1][k+1] += f[i][j][k] \times (m-j)$

  答案按照上述方法统计即可。

  时间复杂度为$O(m^3)$

#include <stdio.h>
typedef unsigned long long u64;
const int N = 305, P = 1e9 + 7;
int n, m, f[N << 1][N][N], c[N << 1], inv[N << 1], sum;
void inc(int &x, int y){
    (x += y) < P ?: x -= P;
}
void inc(int &x, u64 y){
    x = (x + y) % P;
}
int main(){
//  freopen("actor.in", "r", stdin);
//  freopen("actor.out", "w", stdout); 
    int i, j, k, s;
    scanf("%d%d", &n, &m);
    f[1][1][1] = m, c[1] = inv[1] = 1;
    for (i = 2; i <= m << 1; ++i) {
        inv[i] = P - (u64)(P / i) * inv[P % i] % P;
        c[i] = (u64)c[i - 1] * inv[i - 1] % P * (n - i + 1) % P;
    }
    for (i = 1; i <= m << 1; ++i) {
        for (j = 1; j <= m; ++j) {
            for (k = j, s = 0; k >= 1; --k) {
                inc(f[i + 1][j][k], s);
                inc(f[i + 1][j + 1][k + 1], (u64)f[i][j][k] * (m - j));
                inc(s, f[i][j][k]);
            }
            inc(sum, (u64)s * c[i]);
        }
    }
    printf("%d\n", sum); 
}
Actor.cpp

 

 

Guess you like

Origin www.cnblogs.com/ljc20020730/p/11800773.html