Codeforcesエドゥラウンド52 AE

A. Vasyaとチョコレート

シミュレーションの質問。データが破裂します\(int型\) 開きます\(ロング\) \(ロング\)

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
int main(){
    int T; scanf("%d", &T);
    while(T--){
        LL s, a, b, c;
        scanf("%lld%lld%lld%lld", &s, &a, &b, &c);
        LL buy = s / c, free = buy / a * b;
        printf("%lld\n", buy + free);
    }
    return 0;
}

B. Vasyaと孤立頂点

2つの偶数側の間の最小値を、考慮し、答えは\(MAX(N - 2 * M、0)\)

除いて、最大値を考えてみましょう\(m個\)する(1または0 \)\各辺が孤立ない時点までのことで拡大しようと、特別審査員の外側を、あなたが置くことができます(今- 1 \)\をしてもエッジ前へのすべての側面。

#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
typedef long long LL;
LL n, m;
int main(){
    cin >> n >> m;
    cout << max(n - 2 * m, 0ll) << " ";
    if(m == 0) printf("%lld\n", n);
    else if(m == 1) printf("%lld\n", n - 2);
    else{
        int now = 2;
        while(m - now + 1 > 0 && now < n) m -= (now - 1), now++;
        printf("%lld\n", n - now);
    }
    return 0;
}

C.は、それは等しくします

私は、あまりにも弱かっただけを考える\(O(nlogn)\)アプローチ...あなたが使用することができ、木のメンテナンスとプレフィックスの配列を使用することです\(O(LOGN)\)を取得、その後、コストを計算するための時間を大からその上に小さな検索へのポインタ...

#include <cstdio>
#include <iostream>
#include <cmath>
#include <limits.h>
typedef long long LL;
using namespace std;
const int N = 200010;
int n, k, a[N], cnt[N], ans = 0, maxn = -1, minn = INT_MAX;
LL c[N];
void add(int x, LL k){
    for(; x <= maxn; x += x & -x) c[x] += k;
}
LL ask(int x){
    LL res = 0;
    for(; x; x -= x & -x) res += c[x];
    return res;
}
LL inline get(int x){
    return ask(maxn) - ask(x - 1);
}
int main(){
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; i++) 
        scanf("%d", a + i), cnt[a[i]]++, maxn = max(maxn, a[i]), minn = min(minn, a[i]);
    for(int i = maxn; i >= 1; i--)
        add(i, (LL)cnt[i] * i);
    for(int i = maxn; i >= 1; i--)
        cnt[i] += cnt[i + 1];
        
    int i = maxn - 1;
    while(i >= minn){
        ans++;
        while(i - 1 >= minn && get(i) - (LL)(i - 1) * cnt[i] <= k) i--;
        add(i, (LL)i * (cnt[i + 1]) - get(i + 1));
        i--;
    }
    printf("%d\n", ans);
    return 0;
}

そして、実際にそれがダウンしてから、ポインタジャンプのプロセスで使用することができ、接尾辞を扱うことができます(\ O(N))\時間分解スパイシー:

#include <cstdio>
#include <iostream>
#include <cmath>
#include <limits.h>
typedef long long LL;
using namespace std;
const int N = 200010;
int n, k, a[N], cnt[N], po[N], ans = 0, maxn = -1, minn = INT_MAX;
LL c[N];
int main(){
    scanf("%d%d", &n, &k);
    for(int i = 1; i <= n; i++) 
        scanf("%d", a + i), po[a[i]]++, cnt[a[i]]++, maxn = max(maxn, a[i]), minn = min(minn, a[i]);
    for(int i = maxn; i >= 1; i--)
        cnt[i] += cnt[i + 1];

    int i = maxn - 1;
    c[maxn] = (LL)maxn * po[maxn];
    while(i >= minn){
        ans++;
        c[i] = c[i + 1] + (LL)i * po[i];
        while(i - 1 >= minn && c[i] - (LL)(i - 1) * cnt[i] <= k) 
            i--, c[i] = c[i + 1] + (LL)i * po[i];;
        c[i] += (LL)i * (cnt[i + 1]) - c[i + 1];
        i--;
    }
    printf("%d\n", ans);
    return 0;
}

D.三枚

\(ペア<int型、int型> \) 比較関数が付属していますので、多くの労力を節約します。プライオリティキューの書き込み\(BFSが\)あまりにも挑発でしょう...

、それぞれの状態が展開するまで拡張する必要があります$ 3 * N ^ 4つの$の状態の中の選択肢の一つになります\(4 * N \)レベルを、実際には、少なくなります。

総複雑\(O(N * ^ 12 \)。ある5) しないでください(TLE \)\します

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;
typedef pair<int, int> PII;
const int N = 15;
int n, a[N][N];
PII num[N * N];
//0: 车、1: 马: 2、象
int dx[3][8] = {
    {1, -1, 0, 0},
    {1, 1, -1, -1, -2, -2, 2, 2},
    {1, 1, -1, -1},
};
int dy[3][8] = {
    {0, 0, 1, -1},
    {2, -2, 2, -2, 1, -1, 1, -1},
    {1, -1, 1, -1},
};
int size[3] = {4, 8, 4};
int ne[3] = {N, 1, N};
PII step[N][N][N * N][3];
struct Node{
    int x, y, k, m, t, c;
};
bool operator < (const Node &x, const Node &y){
    return x.t == y.t ? x.c > y.c : x.t > y.t;
}
bool inline check(int x, int y){
    return x >= 1 && x <= n && y >= 1 && y <= n;
}
PII bfs(){
    priority_queue<Node> q;
    for(int i = 0; i < 3; i++){
        q.push((Node){ num[1].first, num[1].second, 1, i, 0, 0});
        step[num[1].first][num[1].second][0][i] = make_pair(0, 0);
    }
        
    while(!q.empty()){
        Node u = q.top(); q.pop();
        if(u.k >= n * n){
            return make_pair(u.t, u.c);
        }
        for(int i = 0; i < size[u.m]; i++){
            for(int j = 1; j <= ne[u.m]; j++){
                int nx = u.x + dx[u.m][i] * j, ny = u.y + dy[u.m][i] * j;
                int nm = u.m, nt = u.t + 1, nc = u.c;
                int nk = (num[u.k + 1] == make_pair(nx, ny)) ? u.k + 1 : u.k;
                PII now = make_pair(nt, nc);
                if(!check(nx, ny)) break;
                if(now < step[nx][ny][nk][nm]){
                    step[nx][ny][nk][nm] = now;
                    q.push((Node){nx, ny, nk, nm, nt, nc});
                }
            }
        }
        for(int i = 0; i < 3; i++){
            if(i == u.m) continue;
            int nx = u.x, ny = u.y;
            int nm = i, nt = u.t + 1, nc = u.c + 1;
            int nk = u.k;
            PII now = make_pair(nt, nc);
            if(!check(nx, ny)) break;
            if(now < step[nx][ny][nk][nm]){
                step[nx][ny][nk][nm] = now;
                q.push((Node){nx, ny, nk, nm, nt, nc});
            }
        }
    }
    return make_pair(-1, -1);
}
int main(){
    memset(step, 0x3f, sizeof step);
    scanf("%d", &n);
    ne[0] = ne[2] = n;
    for(int i = 1; i <= n; i++)
        for(int j = 1; j <= n; j++)
            scanf("%d", &a[i][j]), num[a[i][j]] = make_pair(i, j);
    PII res = bfs();
    printf("%d %d\n", res.first, res.second);
    return 0;
}

E.サイドTransmutations

組み合わせの数は、私は確かではないでしょう...

セット\(\)は、文字のセットの長さです。

$ $(1 <= l <= M)$ - 各セグメント$ [+ 1、b_i B_ {1 iは}]用

このセクションでは、長さ設け\(LEN = bを[I] - (B [I - 1] + 1)+ 1 = B [I] - B [I - 1] \)

これは、$ A ^ {lenは}異なるオプションを$ました:

  1. 過去に回し、次いで、対応する過去のある\(A ^ {LEN} - 1 \) 同等の操作がへの貢献に、カウントそれらをカウントすることができるので、(同じ種類を裏返していない含む)プログラムの種類\(\ FRAC {A ^ { LEN} *(A ^ {LEN} - 1)} {2} \)
  2. 同じ裏返し、各だけ過去の番組に対応するように(\ ^ LEN {A})\

次に、2つのソリューションを追加(* \)\\(ANSは\)することができます。

以下のために\([b_m + 1、N - b_m] \) 重複にはなりません選択しないこの選挙で、答えの貢献は次のとおりです。

\(A ^ {N - b_m - (Bの_M + 1)+ 1} = A ^ {N - 2 * b_m} \)

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
const int MOD = 998244353;
const int N = 200010;
int n, m, A, b[N];
int power(int a, int b){
    int res = 1;
    while(b){
        if(b & 1) res = (LL)res * a % MOD;
        a = (LL)a * a % MOD;
        b >>= 1;
    }
    return res;
}
int main(){
    cin >> n >> m >> A;
    for(int i = 1; i <= m; i++) scanf("%d", b + i);
    LL ans = 1;
    for(int i = 1; i <= m; i++){
        LL now = power(A, b[i] - b[i - 1]);
        ans = (ans * ((now + now * (now - 1) / 2) % MOD)) % MOD;
    }
    ans = (ans * power(A, (n - 2 * b[m]))) % MOD;
    cout << ans;
    return 0;
}

おすすめ

転載: www.cnblogs.com/dmoransky/p/11269639.html