【AtCoder】AGC020

A - Move and Win

題解

看兩我的相遇的時候誰先手便可,相遇以後第一個移動的人必輸c++

代碼

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 2005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
int N,A,B;

int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    read(N);read(A);read(B);
    int t = abs(B - A - 1);
    if(t & 1) puts("Alice");
    else puts("Borys");
    return 0;
}

B - Ice Rink Game

題解

二分直接判斷便可spa

代碼

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 100005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
int K;
int64 A[MAXN];
int64 check(int64 x) {
    for(int i = 1 ; i <= K ; ++i) {
    x -= x % A[i];
    }
    return x;
} 
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    read(K);
    for(int i = 1 ; i <= K ; ++i) read(A[i]);
    int64 L = 2,R = 1e18;
    while(L < R) {
    int64 mid = (L + R) >> 1;
    if(check(mid) >= 2) R = mid;
    else L = mid + 1;
    }
    if(check(R) != 2) {puts("-1");return 0;}
    out(R);space;
    R = 1e18;
    while(L < R) {
    int64 mid = (L + R + 1) >> 1;
    if(check(mid) <= 2) L = mid;
    else R = mid - 1;
    }
    out(R);enter;
}

C - Median Sum

題解

咱們把子序列兩兩配對指針

也就是一個子序列選了其中的k個,另外一個子序列選了其中的n - k個,進行配對code

顯然咱們一個對內的子序列,確定一個小於等於\(\frac{sum[n]}{2}\)ci

另外一個大於等於\(\frac{sum[n]}{2}\)rem

因爲全集沒有配對,因此確定中位數就是大於等於\(\frac{sum[n]}{2}\)的第一個字符串

代碼

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
int N,a[MAXN],s,cur;
bitset<4000005> dp[2];
void Solve() {
    read(N);
    for(int i = 1 ; i <= N ; ++i) {read(a[i]);s += a[i];}
    dp[cur].reset();
    dp[cur][0] = 1;
    for(int i = 1 ; i <= N ; ++i) {
    dp[cur ^ 1] = (dp[cur] << a[i]) | dp[cur];
    cur ^= 1;
    }
    for(int i = (s - 1) / 2 + 1; i <= s ; ++i) {
    if(dp[cur][i]) {
        out(i);enter;return;
    }
    }
}

int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
}

D - Min Max Repetition

題解

過於噁心的分類討論題
首先咱們用二分求出最小的k知足題意
求法能夠是默認把A儘量按k分塊而後往能放的空隙裏放B,以後默認把B儘量按k分塊而後能放的空隙裏放Aget

以後呢,咱們特判掉A和B分的段數不相等的狀況
也就是A是1 1 1 1,B儘量按k分塊
B是1 1 1 1,A儘量按k分塊string

以後A和B的段數就相等了
前面確定是A有k個B有1個A有k個B有1個
後面確定是A有1個B有k個A有1個B有k個
咱們二分一個二者的段數it

要求A第一個不爲k的地方不能夠在B第一個不爲k以前兩個
且長度最大
能夠二分

而後咱們把A的每段長度求出來,相同長度的記錄一個重複次數
B同理
以後咱們拿兩個指針每段合併
合併的時候同時求一下這段若是要輸出某一部分是哪裏

代碼

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define pll pair<int64,int64>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}

int64 A,B,C,D,ML;
vector<pll > vA,vB;
bool check(int64 a,int64 b,int64 k) {
    int64 t = (a - 1) / k;
    if(b < t) return false;
    t += 2;
    if(b > t * k) return false;
    return true;
}
void Process(int64 l,int64 r) {
    int p = 0,q = 0;
    int64 len = 1;
    int64 c = 0;
    while(len <= ML) {
    int64 t = min(vA[p].se,vB[q].se);
    vA[p].se -= t;vB[q].se -= t;
    if(len >= l) {
        int64 k = t;
        while(k--) {
        for(int64 i = 1 ; i <= vA[p].fi ; ++i) {
            putchar('A');++c;
            if(c == r - l + 1) return;
        }
        for(int64 i = 1 ; i <= vB[q].fi ; ++i) {
            putchar('B');++c;
            if(c == r - l + 1) return;
        }
        }
    }
    else if(len + t * (vA[p].fi + vB[q].fi) - 1 >= l){
        int64 k = (l - len) % (vA[p].fi + vB[q].fi) + 1;
        int64 h = t - (l - len) / (vA[p].fi + vB[q].fi);
        --h;
        if(k <= vA[p].fi) {
        for(int64 i = k ; i <= vA[p].fi ; ++i) {
            putchar('A');++c;
            if(c == r - l + 1) return;
        }
        for(int64 i = 1 ; i <= vB[q].fi ; ++i) {
            putchar('B');++c;
            if(c == r - l + 1) return;
        }
        }
        else {
        k -= vA[p].fi;
        for(int64 i = k ; i <= vB[q].fi ; ++i) {
            putchar('B');++c;
            if(c == r - l + 1) return;
        }
        }
        while(h--) {
        for(int64 i = 1 ; i <= vA[p].fi ; ++i) {
            putchar('A');++c;
            if(c == r - l + 1) return;
        }
        for(int64 i = 1 ; i <= vB[q].fi ; ++i) {
            putchar('B');++c;
            if(c == r - l + 1) return;
        }
        }
    }
    len += t * (vA[p].fi + vB[q].fi);
    if(vA[p].se == 0) ++p;
    if(vB[q].se == 0) ++q;
    }
}
void Solve() {
    read(A);read(B);read(C);read(D);
    int64 L = 1,R = max(A,B);
    ML = (A + B);
    while(L < R) {
        int64 mid = (L + R) >> 1;
        if(check(A,B,mid) || check(B,A,mid)) R = mid;
        else L = mid + 1;
    }
    vA.clear();vB.clear();
    if(A == ((B - 1) / L)) {
        int64 t = B / L;
        int64 rem = B - L * t;
        vA.pb(mp(0,1));
        vA.pb(mp(1,A));
        if(rem) vB.pb(mp(rem,1));
        vB.pb(mp(L,t));
    }
    else if(B == (A - 1) / L){
        int64 t = A / L;
        int64 rem = A - t * L;
        vA.pb(mp(L,t));
        if(rem) vA.pb(mp(rem,1));
        vB.pb(mp(1,B));vB.pb(mp(0,1));
    }
    else {
        int64 l = max((A - 1) / L + 1,(B - 1) / L + 1),r = min(A,B);
        while(l < r) {
            int64 m = (l + r + 1) >> 1;
            int64 ta = (A - m) / (L - 1);
            int64 tb = (B - m) / (L - 1);
            ta = ta * 2 + 1;
            tb = 2 * m - (tb * 2);
            if(ta + 1 < tb) r = m - 1;
            else l = m;
        }
        if(A > l) {
            int64 ka = (A - l - 1) / (L - 1);
            int64 rem = A - l - ka * (L - 1);
            vA.pb(mp(L,ka));vA.pb(mp(1 + rem,1));vA.pb(mp(1,l - ka - 1));
        }
        else vA.pb(mp(1,l));
        if(B > l) {
            int64 kb = (B - l - 1) / (L - 1);
            int64 rem = B - l - kb * (L - 1);
            vB.pb(mp(1,l - kb - 1));vB.pb(mp(1 + rem,1));vB.pb(mp(L,kb));
        }
        else vB.pb(mp(1,l));
    }
    Process(C,D);
    enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    int Q;
    read(Q);
    while(Q--) {
        Solve();
    }
}

E - Encoding Subsets

題解

這題很迷,複雜度很迷
記錄\(f(S)\)表示\(S\)字符串的答案

而後要麼第一個字符不要\(f(S) += (s[0] + 1)f(2...|S|)\)
要麼就是我枚舉一個長度,枚舉一個壓縮次數
每段都取一個按位且的值,而後計算這個字符串壓縮方案數,以後再加上後面的字符串壓縮方法

寫起來容易一點能夠寫成記搜,而後用map記錄每一個string的答案

跑了不到2s,複雜度超級迷

代碼

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define pll pair<int64,int64>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
const int MOD = 998244353;

int inc(int a,int b) {
    return a + b >= MOD ? a + b - MOD : a + b;
}
int mul(int a,int b) {
    return 1LL * a * b % MOD;
}
void update(int &x,int y) {
    x = inc(x,y);
}
map<string,int> mm;
string operator & (const string &a,const string &b) {
    int l = a.length();
    string c(l,'0');
    for(int i = 0 ; i < l ; ++i) {
        if(a[i] == '1' && b[i] == '1') c[i] = '1';
    }
    return c;
}
int dfs(string s) {
    if(s.empty()) return 1;
    if(s.length() == 1) return s[0] == '0' ? 1 : 2;
    if(mm.count(s)) return mm[s];
    int res = 0;
    res = mul(s[0] == '1' ? 2 : 1,dfs(s.substr(1)));
    int l = s.length();
    for(int d = 1 ; d <= l ; ++d) {
        string t = s.substr(0,d);
        for(int k = d ; k <= l ; k += d) {
            if(k + d - 1 >= l) break;
            t = t & s.substr(k,d);
            update(res,mul(dfs(t),dfs(s.substr(k + d))));
        }
    }
    mm[s] = res;
    return res;
}
void Solve() {
    string s;
    cin >> s;
    out(dfs(s));enter;
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}

F - Arcs on a Circle

題解

把最長的一段挑出來,一個端點做爲0

而後把剩下\(N - 1\)放置的點的位置分紅整數部分和小數部分

咱們枚舉一個排列,是N - 1個點小數的排列順序,能夠認爲排列互不相同

而後能夠抽象出\(C * N\)個點,第\(i\)行第\(j\)列表示整數部分是\(i\)小數部分排行爲\(j\)

記錄一個dp[a][b][S]表示當前在\(a\)點,最遠能到b點,選了點狀態爲S

答案就是dp[C * N][C * N][2^{N - 1} - 1]

代碼

#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define pdi pair<db,int>
#define pll pair<int64,int64>
#define mp make_pair
#define pb push_back
#define enter putchar('\n')
#define space putchar(' ')
#define eps 1e-8
#define mo 974711
#define MAXN 200005
//#define ivorysi
using namespace std;
typedef long long int64;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;char c = getchar();T f = 1;
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 + c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
int a[15],L[15],N,C;
bool vis[15];
int64 f[2][305][(1 << 5) + 5];
db ans,pw;
void Process() {
    memset(f,0,sizeof(f));
    int cur = 0;
    f[cur][min(C * N,L[N] * N)][0] = 1;
    for(int i = 1 ; i < C * N ; ++i) {
        if(i % N == 0) continue;
        memset(f[cur ^ 1],0,sizeof(f[cur ^ 1]));
        int t = i % N - 1;
        for(int j = i ; j <= C * N ; ++j) {
            for(int k = 0 ; k < (1 << N - 1) ; ++k) {
                if(!f[cur][j][k]) continue;
                f[cur ^ 1][j][k] += f[cur][j][k];
                if(k & (1 << t)) continue;
                f[cur ^ 1][min(C * N,max(j,i + L[a[t + 1]] * N))][k ^ (1 << t)] += f[cur][j][k];
            }
        }
        cur ^= 1;
    }
    ans += f[cur][C * N][(1 << N - 1) - 1];
}
void dfs(int dep) {
    if(dep >= N) {
        Process();return;
    }
    for(int i = 1 ; i < N ; ++i) {
        if(!vis[i]) {
            a[dep] = i;
            vis[i] = 1;
            dfs(dep + 1);
            vis[i] = 0;
        }
    }
}
void Solve() {
    read(N);read(C);
    for(int i = 1 ; i <= N ; ++i) read(L[i]);
    sort(L + 1,L + N + 1);
    pw = 1;
    for(int i = 1 ; i < N ; ++i) pw = pw * C;
    dfs(1);
    ans *= 1.0 / pw;
    pw = 1.0;
    for(int i = 2 ; i < N ; ++i) pw = pw * i;
    ans *= 1.0 / pw;
    printf("%.11lf\n",ans);
}
int main() {
#ifdef ivorysi
    freopen("f1.in","r",stdin);
#endif
    Solve();
    return 0;
}
相關文章
相關標籤/搜索