T1
当 (k = 1) 时,如果要查询的数为质数直接输出 (2),如果不是质数,输出它除 (1) 外最小的因子。
当 (k = 2) 时,输出 (lfloor frac x 2 floor + 1)。
如果 (y geq lfloor frac x 2 floor + 1),那么 (x mod y = x - y),当 (y = lfloor frac x 2 floor + 1) 一定最优。
如果 (y leq lfloor frac x 2 floor)
-
当 (x) 是偶数时。
若 (y = lfloor frac x 2 floor),那么 (x mod y = 0)。
若 (y < lfloor frac x 2 floor),那么 (x mod y < y),所以 (x mod y < lfloor frac x 2 floor - 1 = lceil frac x 2 ceil - 1 = x mod y)。 -
当 (x) 是奇数时。
那么 (x mod y < y),所以 (x mod y < lfloor frac x 2 floor = lceil frac x 2 ceil - 1 = x mod y)。
所以无论如何 (lfloor frac x 2 floor + 1) 一定是最优解。
我强烈谴责。。。
#include <cstdio>
#include <cmath>
int main() {
// freopen("mod.in", "r", stdin);
// freopen("mod.out", "w", stdout);
int t;
scanf ("%d", &t);
for(int i = 1; i <= t; i++) {
int x, k, y;
scanf ("%d %d", &x, &k);
if(k == 0) {
bool flag = false;
for(int j = 2; j <= sqrt(x); j++)
if(x % j == 0) {
y = j;
flag = true;
break;
}
if(flag)
printf("%d
", y);
else
printf("2
");
}
else
printf("%d
", x / 2 + 1);
}
return 0;
}
T2
记忆化一下每步操作后的答案。
我强烈谴责。。。
#include <cstdio>
const int MAXN = 1e5 + 5;
const int MAXL = 15;
char s[MAXL];
int vis[MAXN];
int main() {
freopen("var.in", "r", stdin);
freopen("var.out", "w", stdout);
int n, tot;
scanf ("%d", &n);
tot = 0;
for(int i = 1; i <= n; i++) {
int x;
scanf("%s", s);
scanf ("%d", &x);
if(s[0] == 'A')
tot += x;
else if(s[0] == 'S') {
if(s[1] == 'E')
tot = x;
else if(s[1] == 'U')
tot -= x;
}
else if(s[0] == 'B')
tot = vis[i - x - 1];
vis[i] = tot;
}
for(int i = 1; i < n; i++)
printf("%d ", vis[i]);
printf("%d", vis[n]);
return 0;
}
T3
我强烈谴责。。。
#include <cstdio>
const int MAXL = 5;
const int MAXN = 15;
char s[MAXL];
int num[MAXL][MAXN];
// s = 1, p = 2, m = 3
void init() {
for(int i = 1; i <= 3; i++)
for(int j = 1; j <= 9; j++)
num[i][j] = 0;
}
int main() {
// freopen("maj.in", "r", stdin);
// freopen("maj.out", "w", stdout);
int t;
scanf ("%d", &t);
for(int k = 1; k <= t; k++) {
init();
int E = 0, S = 0, W = 0, N = 0, B = 0, F = 0, Z = 0;
for(int j = 1; j <= 14; j++) {
scanf ("%s", s);
if(s[0] == 'E')
E++;
else if(s[0] == 'S')
S++;
else if(s[0] == 'W')
W++;
else if(s[0] == 'N')
N++;
else if(s[0] == 'B')
B++;
else if(s[0] == 'F')
F++;
else if(s[0] == 'Z')
Z++;
else if(s[0] >= '1' && s[0] <= '9') {
int t = s[0] - '0';
if(s[1] == 's')
num[1][t]++;
else if(s[1] == 'p')
num[2][t]++;
else if(s[1] == 'm')
num[3][t]++;
}
}
// printf("%d %d %d %d %d %d %d
", E, S, W, N, B, F, Z);
// for(int i = 1; i <= 3; i++) {
// for(int j = 1; j <= 9; j++)
// printf("%d ", num[i][j]);
// printf("
");
// }
if(num[1][1] >= 1 && num[2][1] >= 1 && num[3][1] >= 1
&& num[1][9] >= 1 && num[2][9] >= 1 && num[3][9] >= 1
&& E >= 1 && S >= 1 && W >= 1 && N >= 1 && B >= 1 && F >= 1 && Z >= 1) {
printf("Thirteen
");
continue;
}
int tot = 0;
if(E == 2)
tot++;
if(S == 2)
tot++;
if(W == 2)
tot++;
if(N == 2)
tot++;
if(B == 2)
tot++;
if(F == 2)
tot++;
if(Z == 2)
tot++;
for(int i = 1; i <= 3; i++)
for(int j = 1; j <= 9; j++)
if(num[i][j] == 2)
tot++;
if(tot == 7) {
printf("Seven
");
continue;
}
bool flag = false;
for(int i = 1; i <= 3; i++) {
int sum = 0;
for(int j = 1; j <= 9; j++)
sum += num[i][j];
if(sum != 14)
continue;
if(num[i][1] >= 3 && num[i][9] >= 3 && num[i][2] >= 1
&& num[i][3] >= 1 && num[i][4] >= 1 && num[i][5] >= 1
&& num[i][6] >= 1 && num[i][7] >= 1 && num[i][8] >= 1) {
flag = true;
break;
}
}
if(flag)
printf("Nine
");
else
printf("I don't know.
");
}
return 0;
}
T4
我们考虑每一个在整个序列排序后位置比当前位置靠前的点。
首先,按照冒泡排序的思路,一次巡视后,比较大的一定会往后走到最后的相对于别的比它更大的数的相对位置。
而比较小的,即需要往前走的则需在很多次巡视后才能到达该位置。
而每次巡视,可以看成某个需要往前走的点最多往前走 (k - 1) 步。
那么我们只需要求需要往前走的点要走个 (k - 1) 步才能到排序后应该在的位置。
小学行程问题总会吧,注意向上取整。
我强烈谴责。。。。
#include <cstdio>
#include <algorithm>
using namespace std;
const int MAXN = 1e5 + 5;
int Max(int x, int y) {return x > y ? x : y;}
struct node {
int x, index;
} s[MAXN];
bool cmp(node a, node b) {
if(a.x != b.x)
return a.x < b.x;
return a.index < b.index;
}
int main() {
// freopen("endt.in", "r", stdin);
// freopen("endt.out", "w", stdout);
int t;
scanf ("%d", &t);
while(t--) {
int n, k;
scanf ("%d %d", &n, &k);
for(int i = 1; i <= n; i++) {
scanf ("%d", &s[i].x);
s[i].index = i;
}
int ans = 0;
sort(s + 1, s + n + 1, cmp);
for(int i = 1; i <= n; i++) {
if(s[i].index > i) {
int t = (s[i].index - i) / (k - 1);
if((s[i].index - i) % (k - 1) != 0)
t++;
ans = Max(ans, t);
}
}
printf("%d
", ans);
}
return 0;
}
其实这套卷子真的很简单。除了最后一道题比较的考思维以外,其它不都是循环结构吗???
真不知道一些人怎么考的。