CF #685 div.2 目前 ABCD
A. Subtract or Divide
题意:给定一个数n,定义2种操作:1.减一,2.除于它的一个真因子(不能为1或n),问,最少需要几次操作可以变为1
思路:简单入门题 ,对于偶数,一般,我们只需要除于
n
2
\frac{n} {2}
2n 变为 2,然后减一,2步操作即可(2除外)
对于奇数,则变为偶数,然后执行上诉步骤(3步,3除外),直接输出,即可
代码: 略
B. Non-Substring Subsequence
题目:B. Non-Substring Subsequence
题意:给定一个二进制串,和2个数l,r决定的一个子串,问该二进制串中是否存在子序列(不能为连续串)等于这个子串
思路: 简单入门题 ,只要在l左边(r左边)搜索是否存在
a
l
a_{l}
al(
a
r
a_{r}
ar),即可,可以轻易证明该思路是合理的。
关键代码:
for (register int i = l - 1; i > 0; i--) if (a[i] == a[l]) { flag = 1; break; }
for (register int i = r + 1; i <= n; i++) if (a[i] == a[r]) { flag = 1; break; }
C. String Equality
题意:给定2个n长字符串a,b(全为小写字母组成),定义2个操作:1.交换相邻字符 2.将k个连续的相同字母变为下一个字母(如a–>b,注z不能变为a) ,问是否可以将a变为b
思路: 模拟 ,因为操作1,可看出决定是否可以变换的主要是各字母数量,因此,定义一个数组,来存储可以用来变换的字母组数(k个一组),即可,详情,见代码(有注释)
关键代码:
//输入A,B2个字符串
scanf("%s", A);
scanf("%s", B);
//统计A,B中各个字母的数量
for (register int i = 0; i < n; i++) {
a[A[i] - 'a']++;
b[B[i] - 'a']++;
}
//flag旗帜,sum表示需要几组变换
bool flag = 0; int sum = 0;
for (register int i = 0; i < 26; i++) {
//前i个字母可以变换的组数
c[i] = a[i] / k;
//特判i==0
if (i != 0)c[i] += c[i - 1];
//i字母剩余个数
a[i] = a[i] % k;
//前i个字母需要变换的组数
sum += (b[i] - a[i]) / k;
//1.字母过多,又凑不够1组 2.需要变换的不成整数组 3. 需要变换的组数大于拥有的组数
if ((a[i] > b[i]) || ((b[i] - a[i]) % k != 0) || sum > c[i]) {
flag = 1;
break;
}
}
D. Circle Game
题意:给定d和k,每个人每次可以将点向右向上移动k个单位,在每个人都最好处理情况下,问不是将点移出半径为 1 4 \frac{1}{4} 41 圆的那个人是谁
⟶ \longrightarrow ⟶ 问, ( a k ) 2 + ( b k ) 2 ≤ c 2 (ak)^{2}+(bk)^{2}\leq c^{2} (ak)2+(bk)2≤c2,在a,b为整数情况下,a + b最大为多少
思路:数学题 ,最好情况下(即走的最多的情况下),为 a = b 或差 1(即,每个人始终朝着不同的一个方向走),因此,算出
d
2
2
k
2
\frac{d^{2}}{2k^{2}}
2k2d2 的最小平方数p,然后再算出在一条边为p*k时的另外一边,观察这一边差值是否
≥
\geq
≥ k (再多走1步就出去了),即可
相信看代码可以更清晰地明白这些
关键代码:
//注意用long long
scanf("%lld%lld", &n, &k);
ll p = (int)sqrt(n * n / (2 * k * k));
ll qk = (int)sqrt(n * n - p * p * k * k);
if (qk < (p + 1) * k) printf("Utkarsh\n");
else printf("Ashish\n");
结尾
蒟蒻不定时补题,有生之年 ,主要是为了监督自己做题补题。