跳转至

博客

P2508 [HAOI2008]圆上的整点

T22:43:00+08:00 洛谷: P2508 【HAOI2008】圆上的整点 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

Lv1 暴力枚举x 20pts

「思路」

暴力出奇迹 没有奇迹。

得到一个象限 乘 4,加上四个坐标轴;或者求1/8圆 乘 8,加上四个坐标轴。

「码」

C++
#include <iostream>
#include <cmath>

#define ll long long

using namespace std;

bool isInteger(const double &x) {
    return x == (ll)x;
}

int main() {
    int r; cin >> r;

    int cnt = 0;
    for (int x = 1; x <= r; x++) {
        if (isInteger(sqrt((ll)r*r - (ll)x*x))) {
            cnt++;
        }
    }
    cout << (cnt << 2) << endl;
    return 0;
}

Lv2 枚举本原勾股数 100pts

「思路」

本原勾股数公式:

\[ \Large \begin{cases} a = m^2 - n^2\\ b = 2mn\\ c = m^2 + n^2 \end{cases} \]

其中 \(m, n \in \N^*, m < n(a, b, c>0)\) 且满足以下条件:

  1. \(gcd(m, n) = 1\)
  2. \(m\)\(n\) 奇偶性不同

本原勾股数就是相互互质的勾股数。

易有:

\[ \Large m = \sqrt{c - n^2} \]

于是可以稍作变形:

\[ \Large \begin{cases} a = c^2 - 2n^2\\ b = 2n\sqrt{c-n^2}\\ c = c \end{cases} \]

这样就可以枚举 \(n\),然后根据 \(c\) 的值计算出 \(m\),检查是否合法。

合法即需要以下条件:

  1. \(c - n^2\) 为完全平方数(这样才能开方出正整数 \(m\)
  2. \(gcd(\sqrt{c - n^2}, n) = 1\)(同本原勾股数公式条件1)
  3. \(\sqrt{c - n^2}\)\(n\) 奇偶性不同(同本原勾股数公式条件2)

那么对于输入的任意一个半径,它上面的格点所对应的勾股数都有可能是由某一个本原勾股数乘以某一倍数 \(k\) 得到的,即 \(r = k \cdot c\),那么我们就可以枚举每一个 \(c\)(也就是枚举 \(r\) 的每一个因数),再对应的 \(c\) 下枚举 \(n\) 得到该 \(c\) 下满足条件的数量,再累加起来即可。

「码」

C++
#include <iostream>
#include <cmath>
#include <vector>

using namespace std;

inline int gcd(const int &a, const int &b) {
    return b ? gcd(b, a%b) : a;
}

inline bool isSquare(const int &x) {
    return (int)sqrt(x)*(int)sqrt(x) == x;
}

void solve(const int &c, int &cnt) {
    for (int n = 1; 2*n*n < c; n++) {
        if (isSquare(c - n*n) && gcd(sqrt(c - n*n), n) == 1 && ((int)sqrt(c - n*n)%2 != n%2)) {
            cnt++;
        }
    }
}

Math.sqrt()

int main() {
    int r; cin >> r;

    int cnt = 0;
    for (int i = 1; i <= sqrt(r); i++) {
        if (r % i) continue;
        solve(i, cnt);
        if (i*i != r) solve(r/i, cnt);
    }

    cout << ((cnt<<1)<<2) + 4 << endl;

    return 0;
}

Lv3 高斯素数 100pts

「思路」

1. 复平面

如果借助复平面来表示格点,则对于以原点为圆心半径为 \(r\) 的圆上任意格点(对应的也就是一个复数 \(z\))都有:

\[ \large z \cdot \bar{z} = r^2 \]

那么问题也就发生了转化:

\(R^2\) 分解、重组为 \(z\)\(\bar{z}\) 的方案数。

2. 高斯素数

引入一个概念 高斯素数,正如 素数 为不能再分解因数的数,高斯素数 就是复平面上不能再继续分解的数,例如 \(3 + 4i = (2+i)\cdot(2+i)\) 可以分解,而 \(2+i\) 不能再继续分解,它就是一个 高斯素数

容易知道 \(\overline{z_1 z_2 \cdots z_n} = \bar{z_1} \bar{z_2} \cdots \bar{z_n}\),那么如果我们将 \(z\)\(\bar{z}\) 彻底分解为一系列 高斯素数 之积,问题也就再次转化:

将这一系列 高斯素数 分为两组,一组中的元素为对应另一组元素的 共轭复数 的方案数。

3. 分解 \(r^2\) 为高斯素数

那么,我们怎么知道 \(r^2\) 如何分解为 高斯素数

首先我们可以将 \(r^2\) 按照唯一分解定理分解:

\[ \large r^2 = p_1^{k_1} p_2^{k_2} \cdots p_k^{k_k} \]

这里面的所有 \(p_i\) 可以分为两类(除去2):

  1. 形如 \(4k + 1(k \in \N^*)\) 型的质因数
  2. 形如 \(4k + 3(k \in \N^*)\) 型的质因数

\(4k\)\(4k+2\) 都不是素数。

这两种质因数在分解为共轭复数的过程中的表现是不同的。

1)\(4k + 1\) 型质因数的分解

引入 费马平方和定理

只有形如 \(4k+1(k \in \N^*)\) 型的素数能够分解为两个正整数的平方和。(除了2,也就是对奇质数成立[质数除了2也都是奇数])

能表示为 两个正整数的平方和 也就自然可以表示为 一对共轭复数之积

\[ \large p = a^2 + b^2 = a^2 - (-b^2) = a^2 - (bi)^2 = (a + bi)(a - bi) \]

而且这 一对共轭复数 还都是 高斯素数

对于这类素数的次方即 \(p^k\) 分解得到的 共轭高斯素数 按照之前所说分成两组的方案数就是 k+1 种。

可以理解为这样一个过程:

如果令 \(p = z \cdot \bar{z}\)

起始的一种方案:A组全为 \(z\),B组全为 \(\bar{z}\)

此后每次交换一对共轭高斯素数,由于每对高斯素数都是相同的,所以无关顺序。

也就是A组中有0个、1个、2个...k个 \(\bar{z}\),一共 k+1 种。

2)\(4k + 3\) 型质因数的分解

还有另一个结论:

形如 \(4k + 3(k \in \N^*)\) 型的素数都是高斯素数,例如7、11、19等都不能再分解为两个复数之积。

那么如果它的指数为奇数,显然不论放在哪一组都无法达到两组分别乘积得到的复数相互共轭的结果,也就是有 \(0\) 种方案。

只有在它的指数为偶数的时候,平分到两组中才行,那自然也就是只有 1 种方案。

也就是 这类高斯素数本身是它自己的共轭复数

不过呢!!!对于这道题来说不用管!!!

为什么呢,因为题目输入的是 \(r\),我们要分解的 \(r^2\) 的每一个质因数的指数注定都是偶数:

\[ \large 若设 \;\;\;\; r = p_1^{k_1} p_2^{k_2} \cdots p_k^{k_k}\;\;\;\; 则\;\;\;\; \large r^2 = p_1^{2k_1} p_2^{2k_2} \cdots p_k^{2k_k} \]
4. 乘法原理 以及 -1,i 和 -i!

那接下来的事情,就是将每个质因数的方案数成在一起即可。

同时其实刚才的分解并不全,正如 \(12 = 3\times2^2 = 3\times(-2)^2\) 一样,刚才我们考虑的高斯素数只是实部大于0的。

而对于任意一种 \(z \cdot \bar{z}\) 来说 \((-z) \cdot (\overline{-z})\)\((iz) \cdot (\overline{iz})\)\((-iz) \cdot (\overline{-iz})\) 也都是一种方案。

在几何直观上的复平面中也就是:关于y轴对称、逆时针旋转90°、顺时针旋转90°。

所以还要乘以四才是最终的格点数量。

5. 关于2

(挖个坑,过一段时间再填

6. 对于本题的一些优化

由于 \(r^2\) 的所有指数都是 \(r\) 的两倍,故不必分解 \(r^2\),直接分解 \(r\) 即可。

那么原本的 k+1 也就成了 k * 2+1,位运算加速也就是 k<<1|1

「码」

C++
#include <iostream>

using namespace std;

int main() {
    int r; cin >> r;

    int ans = 1;
    for (int i = 2; i*i <= r; i++) {
        if (r % i == 0) {
            int cnt = 0;
            do {r /= i; cnt++; } while (r % i == 0);
            if (i % 4 == 1) ans *= cnt<<1|1;
        }
    }
    if (r != 1 && r % 4 == 1) ans *= 1<<1|1;
    cout << (ans<<2) << endl;

    return 0;
}

参考

来,咱们一起找出所有勾股数组~ - 知乎 (zhihu.com)

勾股数有有限多组还是无限多组? - 知乎 (zhihu.com)

走进数论——神奇的勾股数组 - Akarui 的博客 - 洛谷博客 (luogu.com.cn)

分解质因数 - OI Wiki (oi-wiki.org)

高斯素数有类似于素数定理的分布律吗? - 知乎 (zhihu.com)

【官方双语】隐藏在素数规律中的π_哔哩哔哩_bilibili

CF1650F Vitaly and Advanced Useless Algorithms

T16:53:00+08:00 CodeForces:Problem - F - Codeforces

洛谷:CF1650F Vitaly and Advanced Useless Algorithms - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

「题意」

\(n\) 个任务,每个任务要在 \(a_i\) 时刻前做完。(\(a\) 升序)

\(m\) 个计划,每个计划最多只能执行一次,每个计划由 \(e_i\), \(t_i\), \(p_i\) 描述:如果执行了第 \(i\) 个计划,那么 \(t_i\) 时间后,任务 \(e_i\) 会被完成 \(p_i\) 的百分比。

输入 \(T\) 组数据。

输出每组执行的计划个数 \(k\),并按顺序输出执行的计划(若不行则输出 -1,若有多种方案输出其中一种即可)。

「思路」

首先显然有一个贪心的结论:在当前任务未完成时,优先选择能对当前任务有进展的计划(优先完成离ddl近的任务)。

那么对于每一个任务的目标就是 能使进度达到100%的最少时间

很容易借助 差分 得到 每一个任务的限制时间

对于每一个任务,就是个 01背包,对于每一个计划选择 执行不执行

在当前任务省下来的时间,就可以添加到下一个任务的时间中去。

「码」

C++
#include <iostream>
#include <cstring>
#include <tuple> // 元组 c++11
#include <vector>

#define INF 0x7f
#define ll long long

using namespace std;

const int MAXN = 1E5 + 7;

int a[MAXN];
ll dp[200 + 7]; // 最少时间
bool f[MAXN][200 + 7];

int solveTask(int a, vector<tuple<int, int, int>> &plans, vector<int> &ans) {
    // memset(f, 0, sizeof(f));
    memset(dp, INF, sizeof(dp));
    dp[0] = 0;

    int n = plans.size();
    int endk = 0;
    for (int j = 0; j < n; j++) {
        auto [e, t, p] = plans[j]; // 结构化绑定 c++17, auto 自动类型推断 c++11
        for (int k = 200; k >= 0; k--) {
            if (k >= p && dp[k - p] + t < dp[k]) {
                dp[k] = dp[k - p] + t;
                f[j][k] = 1;
                if (k >= 100 && dp[k] <= a && (dp[k] < dp[endk] || endk == 0)) {
                    endk = k;
                }
            } else {
                f[j][k] = 0;
            }
        }
    }

    if (endk == 0) return -1;
    int k = endk, j = n-1;
    for (int j = n-1; j >= 0 && k; j--) {
        if (f[j][k]) {
            auto [e, _, p] = plans[j]; // 结构化绑定 c++17, auto 自动类型推断 c++11
            ans.emplace_back(e); // 在vector末尾原位构造 c++11
            k -= p;
        }
    }
    return dp[endk];
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int T; cin >> T;

    int n, m;
    while (T--) {
        cin >> n >> m;

        a[0] = 0;
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
            a[i-1] = a[i] - a[i-1];
        }

        vector<vector<tuple<int, int, int>>> plans(n); // 元组 c++11
        for (int i = 1, _e, _t, _p; i <= m; i++) {
            cin >> _e >> _t >> _p;
            plans[_e - 1].emplace_back(i, _t, _p); // 在vector末尾原位构造 c++11
        }

        bool f = 0;
        vector<int> ans;
        int saved_time = 0;
        for (int i = 0; i < n; i++) {
            a[i] += saved_time;
            int mint = solveTask(a[i], plans[i], ans);
            if (mint < 0) {
                f = 1;
                break;
            }
            saved_time = a[i] - mint;
        }

        if (f) {
            cout << -1 << endl;
        } else {
            cout << ans.size() << endl;
            // auto 自动类型推断 c++11
            for (auto iter = ans.begin(); iter != ans.end(); iter++) {
                cout << *iter << ' ';
            }
            cout << endl;
        }
    }

    return 0;
}

「几个坑点」

看到那个注释掉的 memset() 没!

大坏蛋!

调了一个小时,问了别人才知道这个 memset() 可能会导致超时!

原因是 f 数组太大了,且这个 memset 在每个 case 中都被调用了 n 次!

这回我可记住了!

CF19B Checkout Assistant

T16:59:00+08:00 CodeForces:Problem - 19B - Codeforces

洛谷:CF19B Checkout Assistant - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

「题目」

购物车中由 \(n\) 件物品,第 \(i\) 件物品价格为 \(c_i\) 且需要花费收银员 \(t_i\) 秒来结算。在收银员正在结算某物品时,可以花费 \(1\) 秒偷取其他的物品(不用结算)。求将所有物品带走所需的最少花费。

「思路」

结算第 \(i\) 件物品 \(\Leftrightarrow\) 拿走 \(t_i+1\) 件物品。

不必考虑拿走哪些物品,只需要总的能拿走的物品数 \(\geq n\) ,所有物品都能带走即可。

即体积为 \(t_i+1\),价值为 \(c_i\),总体积 \(\geq n\),价值最小的01背包。

C++
#include <iostream>
#include <cstring>

#define ll long long

using namespace std;

const int MAXN = 2000 + 7;
const int MAXC = 1E9 + 7;
const int MAXT = MAXN << 1;

ll f[MAXT];
int t[MAXN], v[MAXN];

int main () {
    int n; cin >> n;

    int maxt = 0;
    for (int i = 1; i <= n; i++) {
        cin >> t[i] >> v[i];
        t[i] ++;
        maxt = max(maxt, t[i]);
    }
    maxt += n;

    memset(f, 0x7f, sizeof(f));
    f[0] = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = maxt; j >= t[i]; j--) {
            f[j] = min(f[j], f[j - t[i]] + v[i]);
        }
    }

    ll ans = 2e12 + 7;
    for (int i = n; i <= maxt; i++) {
        if (f[i] < ans) ans = f[i];
    }

    cout << ans << endl;

    return 0;
}

『Python基础』1. 起步

T11:58:00+08:00

一、理解 Python

能被计算机识别的语言,是由 10 组成的二进制码,所以任何编程语言最终都要转换为二进制码才能够被计算机执行。

这里就产生了两个概念,编译型语言解释型语言

  • 编译型语言 一次性地将代码全部翻译为二进制码,如 C/C++ 等。
  • 解释型语言 一边运行一边一句句地翻译。

Python 便是一门 解释型语言,正如 编译型语言 需要 编译器程序 来完成翻译的任务,解释型语言 则需要 解释器程序 来完成翻译的任务。

二、安装 Python解释器

Python官网:Welcome to Python.org

有两个主要的版本,Python2 和 Python3。他们之间有一些较大的语法上的无法兼容的不同,这里安装Python3。

有很多方法可以安装 Python,下面会介绍几种在 Windows 上安装 Python 的方法。

1. 传统安装方法

在Downloads - Windows中可以找到发布的不同版本,现在最新的版本是3.10.2:Latest Python 3 Release - Python 3.10.2,在Files中找到 Windows installer (64-bit) 下载并安装。

Pasted image 20220303111132

勾选上 Add Python 3.10 to PATH ,这会将Python所在的位置添加到系统环境变量的PATH中,然后一路下一步。

环境变量:当使用命令运行程序时会在当前目录以及环境变量中寻找。

然后在终端中输入 python,应该会出现以下输出:

image-20220303112346143

输入 Ctrl + Z 或 exit() 来退出。

2. 使用 Scoop 安装

这种方法是更加简单的,避免了环境变量相关的一些问题,不过可能需要科学上网。

详细内容见 告别繁琐安装界面,使用Scoop管理Windows软件

三、写个 Helloworld 吧

接下来将写一个简单的 HelloWorld 程序,并接触一些简单的概念:变量、输入输出、字符串、注释。

找个地方,新建一个 Helloworld.py,输入以下内容:

Python
x = input("What's your name?")
print("HelloWorld, " + x + "!")

在文件所在位置打开命令行,输入 python Helloworld.py 即可使用解释器执行这个 .py 文件:

image-20230304122332186

其中 x 是一个变量,input() 会以括号里的内容为提示(如果没有则没有提示)获取输入,= 会将右侧的值赋给左侧的变量,print() 会将括号中的内容打印出来,以回车结束。

" 包裹的内容被称为一个字符串,+ 可以将多个字符串拼接,当然也可以使用 ' 来包裹字符串,但是你会发现将如果想要使用 ' 包裹 What's your name? 会有问题,What's 中的 ' 会影响代码的解析。

Python
1
2
3
# Error
x = input('What's your name?')
print("HelloWorld, " + x + "!")

解决方法是在 ' 前插入一个 \ 来转义这个 ',告诉 python 这个 ' 是个字符而不是用来包裹字符串的 '

Python
1
2
3
# Solved
x = input('What\'s your name?')
print("HelloWorld, " + x + "!")

一行中 # 后的内容不会被执行,它被称作 注释,用以在代码中做一些批注,方便人阅读。

自 Python3.8 起,第二行也可以这么写,更加方便:

Python
print(f"HelloWorld, {x}!")

在字符串前加一个f,字符串中以 {} 包括的内容则会被当作 python语句 处理,将得到的值转换为字符串放在对应位置。


你已经踏入 Python 的大门啦~

『C语言教程』7. 文件

T20:50:00+08:00

〇、引入

假如有一个函数 void printValue() ,怎么在这个函数中访问到外部的一个变量呢? 我们使通过一个指针变量来访问的:

C
1
2
3
void printValue(int *x) {
    printf("%d\n", *x);
}

在调用此函数并传入变量地址作为参数时,在函数内部即可通过指针 x 来访问到对应的变量。

文件也是如此,在程序外部有一个文件,我们也可以通过一个类似的 FILE* 型指针变量来访问到文件。

『C语言教程』5. 指针

T18:42:00+08:00

指针是一种特殊的变量类型,有 int* double* 等类型。

声明指针变量:

C
int *a; // 声明一个 int 的指针变量,名为 a

int* aint * a 都可,随意空格

『C语言教程』6. 数组与字符串

T18:50:00+08:00

一、数组

数组,顾名思义。,一坨数。

一个某数据类型的数组可以存储多个该种数据类型的数据,下标从0开始。

「C语言」数组与字符串_数组

上图:普通 int 变量、一维 int 数组、二维 int 数组......

一些概念:

  • 元素 :对于数组 aa[1] 为数组的一个元素

  • 下标 :数学中 \(a_i\)\(i\),这里为数组元素 a[i]i

BJTU-2021届新生寒训 STL专题

T17:45:00+08:00 BJTU-2021届新生寒训 STL专题 - Virtual Judge (vjudge.net)

题源 Codeforces

A - Three Indices

CF:Problem - A - Codeforces

洛谷:CF1380A Three Indices - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目

给定一个 1~n 的排列 \(p_1 ... p_n\),试找到三个下标 \(i, j, k\) 使得:

  • \(i < j < k\)
  • \(p_i < p_j\)\(p_j > p_k\)

思路

假设存在 \(i, j, k\),如果 \(p_j\)\(p_i\) 不相邻,考虑 \(p_{j-1}\)

  • \(p_{j-1} < p_j\) 那么 \(p_{j-1}\) 其实可以代替 \(p_i\),存在了 \(j-1, j, k\) 这三个下标满足题意(1)
  • \(p_{j-1} > p_j\) 那么其实就存在了 \(i, j-1, j\) 这三个下标满足题意(2)

如果令这三个下标为新的 \(i, j, k\) 再考虑新的 \(p_{j-1}\),则要么满足(1)要么一路迭代这样的操作直到 \(i = j-1\) 同样也会达到一个 \(j-1, j, k\) 满足题意。

对于 \(p_k\) 同理,那么可以得到题意等价于存在一个下标 \(j\) 使得 \(p_{j-1} < p_j < p_{j+1}\)


扫一遍 \(O(N)\)

C++
#include <cstdio>
#include <iostream>

using namespace std;

int main() {
    int t; cin >> t;

    // freopen("A.out", "w", stdout);
    int a, b, c, n;
    bool flag;
    while (t--) {
        flag = false;
        a = b = c = 0;
        cin >> n;
        for (int i = 1; i <= n; i++) {
            a = b; b = c; cin >> c;
            if (flag) continue;
            if (a && a<b && b>c) {
                cout << "YES" << endl;
                cout << i - 2 << ' ' << i - 1 << ' ' << i << endl;
                flag = true;
            }
        }
        if (!flag) cout << "NO" << endl;

    }

    return 0;
}

B - Infinity Gauntlet

CF:Problem - A - Codeforces

洛谷:CF987A Infinity Gauntlet - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目

输入有的宝石的颜色,输出对应缺少的宝石名。

思路

map + set。

C++
#include <iostream>
#include <set>
#include <map>

using namespace std;

map<string, string> m;
set<string> s;
int main() {
    // freopen("B.out", "w", stdout);
    m["purple"] = "Power";
    m["green"] = "Time";
    m["blue"] = "Space";
    m["orange"] = "Soul";
    m["red"] = "Reality";
    m["yellow"] = "Mind";

    for (map<string, string>::iterator it = m.begin(); it != m.end(); it++) {
        s.insert(it->second);
    }

    int n; cin >> n;

    string str;
    for (int i = 1; i <= n; i++) {
        cin >> str;
        s.erase(m[str]);
    }

    cout << s.size() << endl;
    for (set<string>::iterator it = s.begin(); it != s.end(); it++) {
        cout << *it << endl;
    }

    return 0;
}

C - Another Sorting Problem

CF:Problem - A - Codeforces

洛谷:CF1575A Another Sorting Problem - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目

输入字符串,排序(奇数位降序,偶数位升序)。

思路

STL + 重载运算符。

C++
#include <algorithm>
#include <iostream>

using namespace std;

const int MAXN = 1E6 + 7;

int n, m;

struct node {
    string str;
    int idx;
    friend bool operator<(const node &a, const node &b) {
        for (int i = 0; i < m; i++) {
            if (a.str[i] == b.str[i]) continue;
            return (i+1)%2 ? a.str[i] < b.str[i] : a.str[i] > b.str[i];
        }
        return 0;
    }
} a[MAXN];

int main() {
    // freopen("C.out", "w", stdout);
    cin >> n >> m;
    for (int i = 1; i <= n; i++) {
        cin >> a[i].str;
        a[i].idx = i;
    }

    sort(a+1, a+n+1);

    for (int i = 1; i <= n; i++) {
        // cout << a[i].str << ' ';
        cout << a[i].idx << ' ';
    }
    cout << endl;

    return 0;
}

D - ConneR and the A.R.C. Markland-N

CF:Problem - A - Codeforces

洛谷:CF1293A ConneR and the A.R.C. Markland-N - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目

求整数1~n中去掉k个数后距离s最近的数与s的距离。

思路

set标记后扫一遍。

C++
#include <set>
#include <cstdlib>
#include <cstdio>

using namespace std;

const int MAXN = 2E9 + 7;
const int MAXK = 1E3 + 7;

int n, s, k;

set<int> closed;
int main() {
    // freopen("D.out", "w", stdout);
    int t; scanf("%d", &t);

    while (t--) {
        closed.clear();
        scanf("%d%d%d", &n, &s, &k);
        for (int i = 0, floor; i < k; i++) {
            scanf("%d", &floor);
            closed.insert(floor);
        }

        if (!closed.count(s)) {
            printf("%d\n", 0);
            continue;
        }

        for (int i = 1; i <= k; i++) {
            if (s-i >= max(1, s-k)) {
                if (!closed.count(s-i)) {
                    printf("%d\n", i);
                    break;
                }
            }
            if (s+i <= min(n, s+k)) {
                if (!closed.count(s+i)) {
                    printf("%d\n", i);
                    break;
                }
            }
        }
    }

    return 0;
}

E - Delete Two Elements

CF:Problem - C - Codeforces

洛谷:CF1598C Delete Two Elements - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

题目

给定n个整数,求删除两个数平均值不变的选法数。

思路

删除两个书平均值不变,即这两个数和为平均值二倍。

map存整数个数。

\(Avg \times 2\) 若非整数,那么选法数必然为0,因为整数加整数不可能为小数

然后枚举,计数。

C++
#include <cstdio>
#include <iostream>
#include <map>

using namespace std;

const int MAXN = 2E5 + 7;

map<int, int> m;
int a[MAXN];
int main() {
    // freopen("E.out", "w", stdout);
    int t; cin >> t;

    int n;
    long long avg2, cnt;
    while (t--) {
        m.clear(); avg2 = cnt = 0;

        cin >> n;
        for (int i = 0; i < n; i++) {
            cin >> a[i];
            avg2 += a[i];
            m[a[i]]++;
        }
        avg2 <<= 1;

        if (avg2 % n) {
            cout << 0 << endl;
            continue;
        }
        avg2 /= n;

        for (int i = 0; i < n; i++) {
            m[a[i]]--;
            cnt += m[avg2 - a[i]];
        }

        cout << cnt << endl;
    }
    return 0;
}

『C语言教程』1. 变量、输入输出

T09:02:00+08:00

一、输出

使用 printf("xxx") 来输出 xxx,比如打印 "Hello World":

C
printf("Hello World");

1. 转义字符(Escape character)

\ 符号会把其后的一个字符 转义 为特殊含义: - \t 制表符(tab) - \n 换行符LF 光标移到下一行开头 - \r 回车符CR 光标移到本行开头

Windows 下常说的换行为 \r\n,而 Linux 为 \n