A Fashion in Berland
A 题目大意
给定一种时尚的夹克衫系纽扣的方式:
所有的纽扣必须有且仅有一个纽扣不系紧,其他的全都系紧。
若是这件衣服只有一个纽扣,则必须系紧。
给定一件有 $n$ $(1 \le n \le 1000)$ 个纽扣的夹克衫,请问是否满足上述时尚方式。
A 解题思路
按照题意模拟即可。
A 代码实现
1 | import java.util.*; |
C Exponential notation
C 题目大意
给定一个正实数 $x$,长度不超过 $10 ^ {6}$,按照要求将其转化成下述简单指数表示形式:
将 $x = a \times 10 ^ {b}$ 而且 $1 \le a \lt 10$
表示为 $aEb$
若 $b$ 为零,则 $Eb$ 部分可以省略。
C 解题思路
按照题意模拟,注意一些细节:
处理无效的前导零。
处理无用的后导零。
处理 $b = 0$ 的情况。
C 代码实现
1 | import java.io.IOException; |
D Swaps in Permutation
D 题目大意
给定一个 $n$ 的全排列,你有 $m$ 种交换。$(1 \le n, m \le 10 ^ 6)$
每种交换用一个数对 $(a, b)$ 表示,表示该交换可以将 $a$ 位置上的数字,与 $b$ 位置上的数字交换。
每次操作你可以进行任意一种交换,你可以进行任意次操作。
每种交换可以进行任意次。
请输出进行若干次操作能够得到的字典序最大的排列。
D 解题思路
我们将每一个位置考虑为一个节点,将每对交换考虑成一条边。
这样便得到了一张图,我们根据其联通关系将其分成若干个联通块。
在某一个联通块内,很容易想到,通过这些交换,可以将这个联通块内的位置上的数字,进行任意的排列。
因此,我们若想要得到字典序最大的排列,则尽可能将大数字放到靠前的位置上去。
所以,在每一个联通块内构造字典序最大的序列,一起组合起来,得到的便是可得到的字典序最大的排列。
使用并查集处理联通关系,在联通块内按照位置从小到大,数字降序放置即可。
D 代码实现
1 | import java.io.IOException; |
E Xor-sequences
E 题目大意
给定 $n$ $(1 \le n \le 100)$ 个数字。
求长度为 $k$ $(1 \le k \le 10^{18})$ 的 $”xor-sequences”$ 异或序列有多少种,结果对 $10^9 + 7$ 取模,异或序列定义如下:
一个序列 $x1, x_2, x_3, \cdots , x_k$ 被称为异或序列,当且仅当对于每一个 $1 \le i \lt k$,都满足 $a_i$ 二进制异或 $a {i + 1}$ 的值的二进制表示中 $1$ 的个数是 $3$ 的非负整数倍。
注意,给定的 $n$ 个数字中,即便存在数字值相同,也考虑为不同数字。
E 解题思路
显然,每个序列若后面想要加一个序列,只需要考虑最后一个数字即可,与再之前的数字无关。
若想在一个序列后面加另外一个序列,只需要考虑前面序列的最后一个数字,和最后一个序列的最前面一个数字即可。
根据此类特性,若我们将这 $n$ 个数字考虑成节点,若数字 $a_i$ 和数字 $a_j$ 满足上述条件,则存在一条 $(i, j)$ 边。
这样的话,我们要求的问题,其实就是在求在这张图中,有多少条经过且只经过 $k$ 个顶点的路径方案存在。
用可达矩阵 $A$ 来表示上述图,根据矩阵乘法定义可知, 在 $A$ 中, $A_{ij}$ 则表示以第 $i$ 个数字开头,以第 $j$ 个数字结尾的长度为 $2$ 异或序列有多少。
同理 $C = A ^{k - 1}$ 表示以第 $i$ 个数字开头,以第 $j$ 个数字结尾的长度为 $k$ 异或序列有多少。
因此,最终答案便是矩阵 $C$ 中所有位置数字在模意义下求和。
根据数据范围,矩阵累乘 $k$ 次显然不可行,因此需要借助快速幂的思想,通过矩阵快速幂求解 $C$ 即可通过此题。
E 代码实现
1 | import java.io.IOException; |
F Couple Cover
F 题目大意
给定 $n$ $(1 \le n \le 10 ^ 6)$ 个正整数 $a_i$ $(1 \le a_i \le 3 \times 10 ^ 6)$。
有 $m$ $(1 \le m \le 10 ^ 6)$ 次询问。
每次询问一个 $p$ $(1 \le p \le 3 \times 10 ^ 6)$,问满足 $a_i * b_j \ge p$ $(i \ne j)$ 的有序对 $(i, j)$ 有多少。
F 解题思路
显然, 合法的有序对共有 $n \times (n - 1)$ 种,暴力枚举每一种方案肯定不可行。
我们发现每次询问的 $p$ 小于等于 $3 \times 10 ^ 6$。
这样的话,我们构造数组 $dp[i]$ 表示乘积小于等于 $i$的方案数有多少。
每次询问的解,显然为 $n \times (n - 1) - dp[p - 1]$。
如何在规定时间内完成 $dp$ 数组的预处理呢。
我们考虑 $cnt[i]$ 表示,值为 $i$ 的数有多少个。
这样的话,考虑值为 $i$ 为 $dp$ 数组造成的贡献有:
若满足 $i*j \le 3 \times 10 ^ 6$
$dp[i*j] += cnt[i] \times cnt[j] (i \ne j)$
$dp[i*j] += cnt[i]\times (cnt[i] - 1) (i = j)$
上述 $dp$ 很容易想到,但是时间复杂度是否允许呢?
根据分析我们可以知道,上述转移的复杂度为 $\Sigma _ {i = 1} ^ {3 \times 10 ^ 6} (3 \times 10 ^ 6 \div i)$
我们令 $mx = 3 \times 10 ^ 6$
也就是 $\frac{mx}{1} + \frac{mx}{2} + \cdots + \frac{mx}{mx}$
上述为调和级数,可以估算为 $mx \times log(mx)$。
F 代码实现
1 | import java.io.IOException; |