Codeforces Round 719 (Div. 3) 补题报告

1 AC情况

ABCDEF1   交互题 \ \colorbox{skyblue}{\color{white}\small\texttt{交互题}}  交互题F2G
Accepted \color{green}\texttt{Accepted} Accepted Accepted \color{green}\texttt{Accepted} Accepted Accepted \color{green}\texttt{Accepted} Accepted Accepted \color{green}\texttt{Accepted} Accepted Accepted \color{green}\texttt{Accepted} Accepted Accepted \color{green}\texttt{Accepted} Accepted--

2 题解

A. Do Not Be Distracted!

Problem - A - Codeforces|Do Not Be Distracted! - 洛谷

题目描述

输入 t t t 组数据。

n n n 项任务,不同任务用不同大写字母表示。每天只能做一项任务,如果一项任务分成了多次做,且中间又做了其他的任务,则会被怀疑。求是否会被怀疑。

题解

桶标记是否任务做过。如果做过,而且有间隔,则会被怀疑。

部分代码(标记间隔)如下:

    vis[s[0]] = 1;
    for (int i = 1; i < n; i++) {
        if (vis[s[i]] && s[i] != s[i - 1]) {
            flag = 1;
            break;
        }
        vis[s[i]] = 1;
    }

B. Ordinary Numbers

Problem - B - Codeforces|Ordinary Numbers - 洛谷

题目描述

输入 t t t 组数据。

如果一个正整数 n n n 在十进制符号中的所有数位都相同,我们就称它为普通数。

对于给定的数 n n n ,求从 1 1 1 n n n 的数中普通数的个数。

题解

打表求出 1 ∼ 1 0 9 1\sim 10^9 1109 所有的普通数。

不同的是,如果每个数遍历检查实在太慢,可以先记录 1 1 1 2 2 2,…, 9 9 9;然后在它们后面加一位,记录 11 11 11 22 22 22,…, 99 99 99;重复,记录 111 111 111 222 222 222,…, 999 999 999;逐次加位数。

查找时只要累计多少个普通数小于等于 n n n 即可。

部分代码(打表)如下:

void init() {
    for (int i = 1; i <= 9; i++) a[++cnt] = i;
    for (int i = 1; a[i] < N; i++) {
        a[++cnt] = a[i] * 10 + a[i] % 10;
    }
}

C. Not Adjacent Matrix

Problem - C - Codeforces|Not Adjacent Matrix - 洛谷

题目描述

输入 t t t 组数据。

1 ∼ n 2 1\sim n^2 1n2 填写进一个 n 2 n^2 n2 的矩阵,使得一个单元的相邻的单元(上、下、左、右挨着的单元)的数值与其不相邻(数值相邻是指两个数绝对值等于一)。无法填写合法矩阵,输出 -1

题解

方法一:

既然上下左右不合法,那么对角线合法。样例:
1 4 8 6 2 5 9 7 3 \def\arraystretch{1.2} \begin{array}{|c|c|c|}\hline 1 & 4 & 8 \\ \hline 6 & 2 & 5 \\ \hline 9 & 7 & 3 \\ \hline \end{array} 169427853
部分代码(构造矩阵)如下:

void func(int n) {
    int cnt = 1;
    for (int i = 1; i <= n; i++)
        ans[i][i] = cnt, cnt++;
    for (int i = 1; i < n; i++) {
        for (int j = 1; j <= n - i; j++)
            ans[j][j + i] = cnt, cnt++;
        for (int j = 1; j <= n - i; j++)
            ans[i + j][j] = cnt, cnt++;
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cout << ans[i][j] << " ";
        }
        cout << endl;
    }
}

方法2:

先填奇数,再填偶数。 样例:
1 3 5 7 9 2 4 6 8 \def\arraystretch{1.2} \begin{array}{|c|c|c|}\hline 1 & 3 & 5 \\ \hline 7 & 9 & 2 \\ \hline 4 & 6 & 8 \\ \hline \end{array} 174396528
部分代码(构造矩阵)如下:

void func(int n) {
    int cnt = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cout << cnt << " ";
            cnt += 2;
            if (cnt > n * n) 
                cnt = 2;
        }
        cout << endl;
    }
}

D. Same Differences

Problem - D - Codeforces|Same Differences - 洛谷

题目描述

输入 t t t 组数据。

一个由 n n n 个整数组成的数组 a a a ,数出索引 ( i , j ) (i, j) (i,j) 中有多少对索引 i < j i < j i<j a j − a i = j − i a_j - a_i = j - i ajai=ji

题解

合法的索引必然满足 a i − i = a j − j a_i-i=a_j-j aii=ajj。因此,只要记录 ( a i − i ) \left(a_i-i\right) (aii) 的值,值相同的就能组成索引。累加索引个数。

部分代码(操作过程)如下:

map<long long, long long> mp;
for (int i = 1; i <= n; i++) {
    cin >> a;
    ans += mp[a - i];
    mp[a - i]++;
}

E. Arranging The Sheep

Problem - E - Codeforces|Arranging The Sheep - 洛谷

题目描述

输入 t t t 组数据。

一个长度为 n n n、由 .* 组成的字符串。其中 . 表示空格, * 表示物体,可以向左或向右移。求用最少的步数让所有的 * 紧靠在一起。

题解

向最中间的 * 靠拢的总步数是最少的。如果向左或向右靠拢都会存在步数重叠。

记录步数即可。

部分代码(找中间和记录过程)如下:

    ll mid = 0, flag = 0, cnt = 0;
    for (ll i = 0; i < n; i++) 
        if (s[i] == '*') cnt++;
    ll find = 0;
    for (ll i = 0; i < n; i++){
        if (s[i] == '*') find++;
        if (find == cnt / 2 + 1) {
            mid = i;
            break;
        }
    }
    flag = mid, ans = 0;
    for (ll i = mid - 1; i >= 0; i--) {
        if (s[i] == '*') {
            ans += flag - i - 1;
            flag--;
        }
    }
    flag = mid;
    for (ll i = mid + 1; i < n; i++) {
        if (s[i] == '*') {
            ans += i - flag - 1;
            flag++;
        }
    }

F1. Guess the K-th Zero (Easy version)

Problem - F1 - Codeforces|Guess the K-th Zero (Easy version) - 洛谷

题目描述

这是一道交互题

输入 n , t ( t = 1 ) , k n,t(t=1),k n,t(t=1),k n n n 表示有一个由 1 1 1 0 0 0 构成的隐藏数组, k k k 表示你要回答第 k k k 0 0 0 的位置。

你可以向交互器提问不超过 20 20 20 个问题,格式如下:

  • ?   l   r ?\ l\ r ? l r:交互器将回答你的问题一个数 n u m num num,表示 ∑ i = l r a i \sum_{i=l}^ra_i i=lrai

每次提问输出后加上代码cout.flush(),用于清理缓冲区来及时向交互器提问。

最后输出格式如下:

  • !   x !\ x ! x x x x 表示第 k k k 0 0 0 的位置。

题解

考虑二分提问区间。

询问 [ l , m i d ] [l,mid] [l,mid],答案为 a n s ans ans,区间元素个数为 x ( x = m i d − l + 1 ) x(x=mid-l+1) x(x=midl+1),考虑:

  • x − a n s ≥ k x-ans\ge k xansk:说明第 k k k 0 0 0 就在 [ l , m i d ] [l,mid] [l,mid] 中, r = m i d r=mid r=mid
  • x − a n s < k x - ans<k xans<k:说明第 k k k 0 0 0 [ m i d + 1 , r ] [mid+1,r] [mid+1,r] 中,则 k k k 更新为在新区间中的次序,即 k = k − ( x − a n s ) k = k - (x-ans) k=k(xans) l = m i d + 1 l = mid+1 l=mid+1

部分代码(主函数)如下:

int main() {
    cin >> n >> t >> k;
    int l = 1, r = n, cnt = 20;
    while (l < r && cnt--) {
        int mid = (l + r) >> 1, ans;
        cout << "? " << l << " " << mid << endl;
        cout.flush();
        cin >> ans;
        if (mid - l + 1 - ans >= k) {
            r = mid;
        } else {
            k -= mid - l + 1 - ans;
            l = mid + 1;
        }
    }
    cout << "! " << l;
    return 0;
}

G. To Go Or Not To Go?

Problem - G - Codeforces|To Go Or Not To Go? - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目描述

输入 n , m , w n,m,w n,m,w n , m n,m n,m 表示地图尺寸, w w w 表示相邻单元格之间移动所用的时间。

每个单元格有三种情况:

  • − 1 -1 1:表示无法通过单元格;
  • 0 0 0:表示可通过,移动时间为 w w w
  • x ( x ≠ 0 ) x(x\ne 0) x(x=0): 表示是一个入口,可以选择当成一个普通单元,移动时间为 w w w;也可以选择当成一个传送门,可以传送到任意一个其他的传送门,所用时间为起点和终点传送门 x x x 之和。

求用最少的时间从 ( 1 , 1 ) (1,1) (1,1) ( n , m ) (n,m) (n,m)

题解

不难发现,传送门最多只走一次。

第一遍 bfs:求从 ( 1 , 1 ) (1,1) (1,1) 到各个传送门的时间;

第二遍 bfs:求从 ( n , m ) (n,m) (n,m) 到各个传送门的时间。

求出如果走传送门,需要的最短时间。

第三遍 bfs:求不走传送门的时间(可能不存在路径)。

比较走和不走传送门的时间,求最小值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值