Google Kickstart Round G 2017

Problem A. Huge Numbers

Problem

Professor Shekhu has another problem for Akki today. He has given him three positive integers A, N and P and wants him to calculate the remainder when AN! is divided by P. As usual, N! denotes the product of the first N positive integers.

Input

The first line of the input gives the number of test cases, T. T lines follow. Each line contains three integers A, N and P, as described above.

Output

For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the answer.

Limits

1 ≤ T ≤ 100.
Small dataset

1 ≤ A ≤ 10.
1 ≤ N ≤ 10.
1 ≤ P ≤ 10.
Large dataset

1 ≤ A ≤ 10^5.
1 ≤ N ≤ 10^5.
1 ≤ P ≤ 10^5.
Sample
Input
2
2 1 2
3 3 2
Output
Case #1: 0
Case #2: 1

In Sample Case #1, the answer is the remainder when 21! = 2 is divided by 2, which is 0.
In Sample Case #2, the answer is the remainder when 33! = 36 = 729 is divided by 2, which is 1.

题意

\((A^{N!}) \% p\)

Small

暴力求N!然后快速幂即可。复杂度O(N!lg(N!))

Large

\((A^{N!}) \% p = (A^{(N-1)!})^N\%p =(A^{(N-1)!}\%p)^N\)
递推求\((A^{(N-1)!}\%p)\)然后快速幂即可。 复杂度 O(nlgn)

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll a, n, p;
ll quick_mod(ll base, ll n) {
    ll ans = 1;
    while (n) {
        if (n&1) ans = ans * base % p;
        n >>= 1;
        base = base * base % p;
    }
    return ans;
}
int main() {
    ios::sync_with_stdio(false);
    int t;
    cin >> t;
    for (int tt = 1; tt <= t; tt++) {
        cin >> a >> n >> p;
        int ans = a % p;
        for (int i = 2; i <= n ; i++) {
            ans = quick_mod(ans, i);
        }
        printf("Case #%d: %lld\n", tt, ans);
    }
    return 0;
}

Problem B. Cards Game

Problem

Professor Shekhu was a famous scientist working in the field of game theory in the early days of computer science. Right now, he's working on a game which involves a box containing N distinct cards. The i-th of these cards has a red number written on one side, and a >blue number written on the other side. Both of these numbers are positive integers. The game proceeds as follows:

The player starts with a total of 0 points. The objective of the game is to finish with the lowest possible total.
As long as there are at least two cards remaining in the box, the player must repeat the following move:
Remove two cards of their choice from the box. Choose a red number R from one card and a blue number B from the other card.
Add the value R ^ B to the total, where ^ denotes bitwise XOR operation.
Return one of the two cards to the box, and remove the other from the game.
The game ends when there is only one card remaining in the box (and so it is impossible to make another move).
Professor Shekhu has summoned his best student, Akki, to play this game. Can you help Akki find the minimum possible total, considering all possible ways in which he can play the game?

Input

The first line of the input contains an integer T, the number of test cases. T test cases follow; each test case consists of three lines:
First line of the each test case will contain an integer N.
The first line contains a positive integer N: the number of cards in the box.
The second line contains a list of N positive integers Ri; the i-th of these represents the red number on the i-th card.
The third line contains a list of N positive integers Bi; the i-th of these represents the blue number on the i-th card.
Output

For each test case, output one line containing Case #x: y, where x is the test case number (starting from 1) and y is the minimum possible total that Akki can attain, if he plays optimally.

Limits

1 ≤ T ≤ 100.
1 ≤ Ri ≤ 10^9.
1 ≤ Bi ≤ 10^9.
Small dataset

2 ≤ N ≤ 5.
Large dataset

2 ≤ N ≤ 100.
Sample
Input
2
2
1 2
3 3
3
1 101 501
3 2 3
Output
Case #1: 1
Case #2: 5

In Sample Case #1, Akki has only one move in which he picks up the available cards and has two options.
1、He can choose red number from the first card and blue number from the second card to add 1 ^ 3 = 2 to the total.
2、He can choose red number from the second card and blue number from the first card to add 2 ^ 3 = 1 to the total.

The second option is better and the answer is 1.
In Sample Case #2, one optimal strategy is to take the red number from first card and the blue number from second card, add 1 ^ 2 = 3 to the total, and return first card to the box. Then, take the red number from first card and the blue number from third card, add 1 ^ 3 = 2 to the total, and return either of the cards to the box. The final total is 5.

题意

每次从N张牌中选择两张,代价为min(r[i]^b[j], r[j]^b[i]), 然后从两张中选择一张删去进入下一轮,循环直至只剩一张牌,求最小代价和。

Small

枚举每次的选择暴力dfs即可。复杂度f(n) = 2 * C(n, 2) * f(n-1) ==> O(N! * (N-1)!)

Large

转化为求图的最小生成树。

初始状态是所有的牌,每个牌之间有一条边,权值即为相应的代价。每一轮相当于从牌的集合里选择一张牌删去,删除的代价为该牌与 剩下的牌的任意一个连接边的权值。这与prim算法的原理是一样的,也就是可以转化为图的最小生成树问题,初始状态是一个完全图。
用prim算法或kruskal算法解决即可。复杂度O(nnlg(n))

#include <bits/stdc++.h>
using namespace std;

struct edge{
    int from, to, v;
    bool operator< (const edge& rhs) const {
        return v < rhs.v;
    }
};

int r[100], b[100], p[100];
vector<edge> graph;

int findp(int x){
  return x == p[x] ? x : p[x] = findp(p[x]);
}

int main(){
    int t;
    cin >> t;
    for(int tt = 1; tt <= t; tt++){
        int n;
        cin >> n;
        for(int i = 0; i < n; i++) cin >> r[i];
        for(int i = 0; i < n; i++) cin >> b[i];
        graph.clear();

        for(int i = 0; i < n; i++){
            for(int j = i + 1; j < n; j++){
                int x = r[i] ^ b[j], y = r[j] ^ b[i];
                graph.push_back({i, j, min(x, y)});
            }
        }

        sort(graph.begin(), graph.end());

        for(int i = 0; i < n; i++) p[i] = i;
        long long ans = 0;

        for(edge &e : graph){
            int pa = findp(e.from), pb = findp(e.to);
            if(pa != pb){
                ans += e.v; p[pb] = pa;
            }
        }
        printf("Case #%d: %lld\n", tt, ans);
  }
  return 0;
}
posted @ 2017-10-23 20:47  hxidkd  阅读(572)  评论(0编辑  收藏  举报