Codeforces Round 747 div.2 A-E

A. Consecutive Sum Riddle

题意:给定一个 \(n\),要找出 \(l,r\) 使得 \(\sum_{i=l}^{r}i=n\)

解:显然,从 \(-n+1\) 加到 \(n\) 即可

void solve(){
    ll n;
    cin >> n;
    cout << -n+1 << ' ' << n << '\n';
}

B. Special Numbers

题意:找第 \(k\)\(n\) 好数,\(n\) 好数就是可以被 \(n\) 的不同次幂组成,比如 \(n^0+n^2...\) 的方式表示

解:把 \(k\) 转化为二进制,然后每一位按照 \(n\) 的次幂加权计算即可

void solve(){
    ll n, k;
    cin >> n >> k;
    ll ans = 0, t = 1;
    while(k > 0){
        if(k & 1){
            ans = (ans + t) % mode;
        }
        k >>= 1;
        t = t * n % mode;
    }
    cout << ans << '\n';
}

C. Make Them Equal

题意:给出一个字符串 \(s\) 和字符 \(c\),可以进行若干次操作,每次操作可以选择一个数 \(x\),然后令字符串中所有下标不能被 \(x\) 的整除的位置上的字符变成 \(c\),问最少多少次操作可以使字符串全变成 \(c\)

解:由于 \(n>2\),两次操作分别选择 \(n\)\(n-1\) 一定可以完成,那么只需要考虑能不能一次完成

一次完成要求存在一个数 \(x\),串中所有可以被 \(x\) 整除的位置上都已经是 \(c\) 了,暴力枚举即可,复杂度比较玄学但它就是 \(nlogn\)

后来又听了无敌的会长的优化方案:只需要枚举 \(n/2\) 以上的 \(x\) 即可,因为更小的 \(x\) 总有一个倍数比它更优,复杂度 \(2n\)

void solve(){
    int n;
    char c;
    string s;
    cin >> n >> c >> s;
    s = "0" + s;
    for(int i=1;i<=n;i++){
        bool flg = true;
        for(int j=i;j<=n;j+=i){
            if(s[j] != c){
                flg = false;
                break;
            }
        }
        if(flg){
            if(i == 1){
                cout << "0\n";
                return;
            }
            cout << 1 << '\n';
            cout << i << '\n';
            return;
        }
    }
    cout << 2 << '\n';
    cout << n-1 << ' ' << n << '\n';
}

D. The Number of Imposters

题意:有 \(n\) 个人和 \(m\) 个陈述,每个陈述形如:\(i,j,imposter/crewmate\) 表示 \(i\)\(j\) 是说真话的人/说谎者,问说谎话的人最多有几个

解:注意到一个性质:如果 \(i\)\(j\) 说的是谎话,那么 \(i\)\(j\) 必定相反;如果 \(i\)\(j\) 说的是真话,那么 \(i\)\(j\) 相同。

那么每个陈述都可以转化为一条边,对每个联通块进行染色后取较多的颜色加入贡献即可

int st[maxn];
struct Edge{
    int t, nt, tp;
}e[maxn << 1];
int head[maxn], ecnt = 0;

inline void add(int x, int y, int tp){
    e[++ecnt].t = y;
    e[ecnt].tp = tp;
    e[ecnt].nt = head[x];
    head[x] = ecnt;
}

int num[2];
bool dfs(int p){
    for(int i=head[p];i;i=e[i].nt){
        int v = e[i].t;
        if(st[v] == -1){
            st[v] = st[p] ^ e[i].tp;
            num[st[v]]++;
            if(!dfs(v)) return false;
        }else{
            if(st[v] != (st[p] ^ e[i].tp)) return false;
        }
    }
    return true;
}

void solve(){
    int n, m;
    cin >> n >> m;

    ecnt = 0;
    for(int i=1;i<=n;i++){
        head[i] = 0;
        st[i] = -1;
    }

    for(int i=1;i<=m;i++){
        int x, y; string s;
        cin >> x >> y >> s;
        int tp = (s[0] == 'i');
        add(x, y, tp);
        add(y, x, tp);
    }
    int ans = 0;
    for(int i=1;i<=n;i++){
        if(st[i] == -1){
            st[i] = 1;
            num[1] = 1;
            num[0] = 0;
            if(!dfs(i)){
                cout << "-1\n";
                return;
            }
            ans += max(num[0], num[1]);
        }
    }
    cout << ans << '\n';
}

E1. Rubik's Cube Coloring (easy version)

题意:给一颗 \(k\) 层的完全二叉树,每个节点有一个颜色(共六种),要求每个节点和其相邻节点颜色不能相同,并且规定了三对不能相邻的颜色,问有多少中染色方案

解:答案为 \(4^{2^n-2}\times 6\)

ll qpow(ll x, ll p){
    ll r = 1;
    while(p > 0){
        if(p & 1) r = r * x % mode;
        x = x * x % mode;
        p >>= 1;
    }
    return r;
}

void solve(){
    int n;
    cin >> n;
    cout << qpow(4, (1ll << n) - 2) * 6 % mode << '\n';
}

Codeforces Round 747 div.2 A-E
http://www.lxtyin.ac.cn/2021/10/09/题解/Codeforces Round 747 div.2/
作者
lx_tyin
发布于
2021年10月9日
许可协议