A - Last Two Digits
题目大意
给定正整数$N$,求$N$的后两位。
$100\le N\le 999$
输入格式
$N$
输出格式
输出$N$的后两位,注意输出可能有前导0
。
样例
$N$ | 输出 |
---|---|
$254$ | 54 |
$101$ | 01 |
分析
题目已经规定$N$是三位数,因此无需使用整数输入,直接将输入看成字符串,输出后两位即可。
代码
|
|
B - Practical Computing
题目大意
输出$N$个整数序列$A_0,\dots,A_{N-1}$。它们按如下定义:
- $A_i$的长为$i+1$。
- $A_i$的第$j+1$个元素记为$a_{i,j}$($0\le j\le i < N$),即:
- 当$j=0$或$j=i$时,$a_{i,j}=1$;
- 否则,$a_{i,j}=a_{i-1,j-1}+a_{i-1,j}$。
$1\le N\le 30$
输入格式
$N$
输出格式
输出$N$行。第$i$行上有$A_{i-1}$中的$i$个数,用空格分隔。
样例
样例输入1
|
|
样例输出1
|
|
样例输入2
|
|
样例输出2
|
|
分析
其实不用读题,看一眼样例,是不是很眼熟?没错,就是著名的杨辉三角。
不知道也没关系(不过应该也没人不知道),直接按题目要求($i,j$正序)依次计算即可。时间复杂度$\mathcal O(n^2)$,空间复杂度$\mathcal O(n)$或$\mathcal O(n^2)$。详见代码$1,2$。
继续考虑,杨辉三角中$a_{i,j}=C_j^i$,所以可以用$\mathcal O(1)$的空间计算,时间不变,代码待会补。
代码
- 代码$1$(普通方法+无优化+
cin
/cout
,$7\text{ms}~3604\text{KB}$)
时间:$\mathcal O(n^2)$
空间:$\mathcal O(n^2)$
难度:低1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
#include <iostream> ing namespace std; t arr[35][35]; t main() int n; cin >> n; for (int i = 0; i < n; i++) { arr[i][0] = 1; arr[i][i] = 1; } for (int i = 2; i < n; i++) { for (int j = 1; j < i; j++) { arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j]; } } for (int i = 0; i < n; i++) { for (int j = 0; j <= i; j++) { cout << arr[i][j] << " "; } cout << endl; } return 0;
- 代码$2$(普通方法+滚动表+
scanf
/printf
,$6\text{ms}~1656\text{KB}$)
时间:$\mathcal O(n^2)$
空间:$\mathcal O(n)$
难度:中低1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
nclude <cstdio> ing namespace std; t a[35]; t main() int n; scanf("%d", &n); a[0] = 1, puts("1"); for(int i=1; i<n; i++) { putchar('1'); for(int j=i-1; j>0; j--) a[j] += a[j - 1]; for(int j=1; j<i; j++) printf(" %d", a[j]); a[i] = 1, puts(" 1"); } return 0;
C - K Swap
题目大意
给定长度为$N$的序列$A=(a_1,a_2,\dots,a_N)$和整数$K$,你可以重复下列操作任意次:
- 选择整数$1\le i\le N-K$,交换$a_i$和$a_{i+K}$。
问:是否能通过上述操作将$A$按升序排列?
$2\le N\le 2\times 10^5$
$1\le K\le N-1$
$1\le a_i\le 10^9$
输入格式
$N~K$
$a_1~\dots~a_N$
输出格式
如果可以达到目标,输出Yes
;否则,输出No
。
样例
样例输入1
|
|
样例输出1
|
|
该样例中,$A=(3,4,1,3,4),K=2$。一种完成任务的操作如下:
- 交换$a_1$和$a_3$,此时$A=(1,4,3,3,4)$;
- 交换$a_2$和$a_4$,此时$A=(1,3,3,4,4)$,排序完成。
样例输入2
|
|
样例输出2
|
|
$K=3$,无法将$A$排序。
样例输入3
|
|
样例输出3
|
|
可以不进行操作。
分析
题目可以看成:在$a_i,a_{K+i},a_{2K+i},\dots$($1\le i < K$)中的元素是可以两两相邻交换的。那么,根据冒泡排序的原理,这些元素是可以直接排序并放入原位置上的。此时,只需依次对于$i=1,2,\dots,K-1$的上述序列并排序、放回原位,最终检查是否已被排成升序即可。
代码
|
|
特别: 本题涉及到很多数组操作,使用Python
代码量非常小(使用数组切片和sorted()
),所以也是一道很好的Python
数组练习题。因此,这里破例提供Python
示例代码:
|
|
D - Together Square
题目大意
给定整数$N$。求正整数对$(i,j)$的个数,满足:
- $1\le i,j\le N$
- $i\times j$是一个完全平方数(即$1^2,2^2,3^2,\dots$)
$1\le N\le 2\times 10^5$
输入格式
$N$
输出格式
输出答案。
样例
$N$ | 输出 |
---|---|
$4$ | $6$ |
$254$ | $896$ |
分析
注意$N$较大,所以最容易想到的$\mathcal O(n^2)$暴力枚举肯定是不行的,然后仔细思考后发现可以枚举整数对$(x,y)$($1\le x,y\le\lfloor\sqrt N\rfloor$),当$x,y$互质时将答案加上$\frac N {\max\{x^2,y^2\}}$,这样答案正确,建议读者自行思考原因。
时间复杂度计算:
- 循环(次数$\sqrt N$,枚举$x$)
- 循环(次数$\sqrt N$,枚举$y$)
gcd
最大公约数算法(辗转相除法$\log\max\{x,y\}\approx\log\sqrt N$,判断互质)
- 循环(次数$\sqrt N$,枚举$y$)
综上,总时间复杂度为$\mathcal O(\sqrt N\times\sqrt N\times\log\sqrt N)=\mathcal O(N\log\sqrt N)$。
代码
|
|
E - Small d and k
题目大意
给定一个由$N$个点和$M$条边组成的简单无向图。
对于每个$i=1,2,\dots,M$,第$i$条边连接顶点$a_i$和$b_i$。
已知 ==每个顶点的度数不超过3==,回答下列$Q$个查询,第$i$个查询为:
- 求与顶点$x_i$距离不超过$k_i$的点的下标之和。
$1\le N,Q\le 1.5\times 10^5$
$0\le M\le \min\{\frac{N(N-1)}2,\frac32N\}$
$1\le a_i < b_i\le N$,$(a_i,b_i)$互不相同。
$1\le x_i\le N$,==$0\le k_i\le 3$==
输入格式
$N~M$
$a_1~b_1$
$\vdots$
$a_M~b_M$
$Q$
$x_1~k_1$
$\vdots$
$x_Q~k_Q$
输出格式
输出$Q$行。第$i$行应包含第$i$个查询的答案。
样例
样例输入
|
|
样例输出
|
|
样例解释:AtCoder 254E - Small d and k #sample
分析
注意这题数据范围,这是解体的关键:
- 减少算法耗时:
- $0\le k\le 3$
- 顶点度数$~\le3$
- 根据乘法原理,一次查询最大符合条件的顶点数为$3^3+1=28$个
- 防止常数问题:
- $1\le N\le \textbf{1.5}\times 10^5$
- 时间限制$3.5\text{s}$
因此,使用简单的暴力$\text{BFS}$正好符合题目数据范围。详见代码。
代码
注意dis
数组的清零操作,无需全部清零,只需把刚刚改过的清零即可。
|
|