Codeforcesエドゥラウンド49 AE

A.回文ツイスト

変更する必要があります。だから、作る\([I] = A [私は+ N - 1] \)

同じに行きますが、満たさなければならないのいずれかの前に\([I] = A [私は+ N - 1] \)を

いずれかの2つの文字間の差満たす必要があり、会う\(2 \)までの距離を。

#include <cstdio>
#include <iostream>
#include <cmath>
using namespace std;
const int N = 110;
int n;
char str[N];
bool judge(){
    for(int i = 1; i <= n / 2; i++)
        if(abs(str[i] - str[n - i + 1]) != 2 && abs(str[i] - str[n - i + 1]) != 0) return false;
    return true;
}
int main(){
    int T; scanf("%d", &T);
    while(T--){
        scanf("%d%s", &n, str + 1);
        if(judge()) puts("YES");
        else puts("NO");
    }
    return 0;
}

チェスボード上のB.番号

質問場合は、法則を見つける\は、(N- \)奇数である場合、各行可能\((N - 1)/ 2 \) または\((N + 1)/ 2 \) 番号、パーティションを考慮することができます。

#include <iostream>
#include <cstdio>
#define int long long
using namespace std;
int n, q;
signed main(){
    scanf("%lld%lld", &n, &q);
    for(int i = 1; i <= q; i++){
        int x, y; scanf("%lld%lld", &x, &y);
        int num = 0;
        if(n % 2){
            if((x + y) % 2 == 0){
                if(x % 2) num = (x - 1) * n / 2 + y / 2 + 1;
                else num = (x - 2 + 1) * n / 2 + 1 + y / 2;
            }else{
                if(x % 2) num = n * n / 2 + 1 + (x - 1) * n / 2 + y / 2;
                else num = n * n / 2 + (x - 2 + 1) * n / 2 + 1 + y / 2 + 1;
            }
        }else{
            if((x + y) % 2 == 0){
                if(x % 2) num = (x - 1) * (n / 2) + y / 2 + 1;
                else num = (x - 1) * (n / 2) + y / 2;
            }else{
                if(x % 2) num = n * n / 2 + (x - 1) * (n / 2) + y / 2;
                else num = n * n / 2 + (x - 1) * (n / 2) + y / 2 + 1;
            }
        }
        printf("%lld\n", num);
        
    }
    return 0;
}

C.最小値のRectangle

長さの矩形に配置された側\(\)、\ (Bの\) および\(A <= B \) その後:

\(\ FRAC {P ^ 2} {S} = \ FRAC {(2(A + B))^ 2} {*のB} = FRAC \ {図4(a)^ 2 + 4(b)^ 2 + 8AB} {* bの} = 4(\ FRAC {A}、{B} + \ FRAC {B} {A})+ 8 \)

そう\(\ FRAC {A}、{ B} + \ FRAC {B} {A} \) 最小、ちょうどので\(\ FRAC {B} { A} \) 最小両方ので\(\ FRAC {B {A}}> = 1 \)が、\(\ FRAC {A}、{B} <= 1 \) 後者は、和に影響を及ぼさないようにします。

#include <iostream>
#include <cstdio>
#include <limits.h>
#include <cstring>
#include <algorithm>
using namespace std;
const int SIZE = 10010;
int n, a, cnt[SIZE], d[SIZE << 1], tot, ansA, ansB;
double c, minn;
 
int main(){
    int T; scanf("%d", &T);
    while(T--){
        memset(cnt, 0, sizeof cnt);
        bool success = false; tot = 0;
        minn = 10001;
        scanf("%d", &n);
        for(int i = 1; i <= n; i++) {
            scanf("%d", &a), cnt[a]++;
            if(cnt[a] == 2) d[++tot] = a;
            if(cnt[a] == 4) d[++tot] = a;
        } 
        sort(d + 1, d + 1 + tot);
        for(int i = 1; i < tot; i++){
            if(d[i] == d[i + 1]){ ansA = d[i], ansB = d[i + 1]; break; }
            c = (double)d[i + 1] / d[i];
            if(c < minn)ansA = d[i], ansB = d[i + 1], minn = c;
        }    
        printf("%d %d %d %d\n", ansA, ansA, ansB, ansB);
    }
    return 0;
}

D.マウス・ハント

各ブロックユニコムのために、位置に配置された(サブリングを含む)セレクタリングは、ラットのいずれかを挟ま。

予選ポジションでは、最小値をとるの答えです。

選択された点のコストより大きくなるかもしれない複数の点を選択する場合。

緑色の点を選択した場合、1 + 20を選択するが、各部屋には、マウスを取り除くことができることを保証するためには、その2000は必須なので、>ユニコ​​ム速い複数のポイントを過ごすの選択は一点のみを選択します。

#include <iostream>
#include <cstdio>
#include <vector>
#include <limits.h>
using namespace std;
const int N = 200010;
int n, c[N], a[N], ans;
bool st[N], vis[N];
vector<int> G[N], edge, val;

void dfs(int u){
    if(vis[u]){
        val.push_back(u);
        while(edge.size() && edge.back() != u)
            val.push_back(edge.back()), edge.pop_back();
        return ;
    }
    vis[u] = true, edge.push_back(u), dfs(a[u]);
}
void mark(int u){
    for(int i = 0; i < G[u].size(); i++){
        int v = G[u][i];
        if(!st[v]) st[v] = true, mark(v);
    }
}
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i++) scanf("%d", c + i);
    for(int i = 1; i <= n; i++) {
        scanf("%d", a + i);
        G[i].push_back(a[i]);
        G[a[i]].push_back(i);
    } 
    for(int i = 1 ; i <= n; i++){
        if(!st[i]){
            val.clear(); edge.clear();
            dfs(i);
            int res = INT_MAX;
            for(int i = 0; i < val.size(); i++)
                res = min(res, c[val[i]]);
            ans += res;
            st[i] = true, mark(i);
        }
    }
    printf("%d", ans);
    return 0;
}

E.逆のぬりえ

少し問題解決のほとんど理解を読んだ後、自閉症。

セット\([I] [J F ] [K] \) の長さの\(Iは\) 連続充填の最大数\(K \) までの最長の連続コーティングの色数の尾\(J \)プログラムの数

それは、この状態が状態に拡張することができると考えられる以下のとおりです。

  • 新しい色が終了する前と同じままである場合、\(Fは[Iは+ 1] [+ J. 1] [MAX(1 + J、K)] \)
  • 同じ、ではありません\(F [私は+ 1] [1] [MAX(1、K)]は、\)

\(CNT [i]が\)実際の長さです\(私は\) 彼らが会うように、プログラムのすべての数の、:

\(私はJ <K \を*)、\ (CNT [I] * CNTは、[J] \)回答に追加することができ

... ...

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;
const int N = 510, mod = 998244353;
typedef long long LL;
int n, k, f[2][N][N], cnt[N];
void update(int &a, int b){ a = (a + b) % mod; }
int main(){
    scanf("%d%d", &n, &k);
    f[0][0][0] = 1;
    for(int i = 0; i < n; i++){
        int pre = i & 1, now = pre ^ 1;
        memset(f[now], 0, sizeof f[now]);
        for(int j = 0; j <= n; j++){
            for(int k = 0; k <= n; k++){
                update(f[now][j + 1][max(j + 1, k)], f[pre][j][k]);
                update(f[now][1][max(1, k)], f[pre][j][k]);
            }
        }  
    }
    for(int i = 0; i <= n; i++){
        for(int j = 0; j <= n; j++){
            update(cnt[i], f[n & 1][j][i]);
        }
    }
    LL ans = 0;
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= n; j++){
            if(i * j < k)
                ans = (ans + (LL)cnt[i] * cnt[j]) % mod;
        }
    }
    printf("%lld", (ans / 2) % mod);
    return 0;
}

おすすめ

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