A:水
直接观察得到只有两种情况,要么2次,要么4次,如果边界上有1则为2次,否则为4次
AC代码:
#include <cstdio>
#include <cstring>
const int MAX_NUMBER = 55;
int maps[MAX_NUMBER][MAX_NUMBER];
int n, m;
int main() {
scanf("%d%d", &n, &m);
int flag = 0;
for (int i = 1; i <= n; i++) {
for (int j = 1; j <= m; j++) {
scanf("%d", &maps[i][j]);
if (maps[i][j]) {
if (i == 1 || i == n) {
flag = 1;
}
if (j == 1 || j == m) {
flag = 1;
}
}
}
}
if (flag) {
printf("2\n");
}
else {
printf("4\n");
}
return 0;
}
B题
n很大,首先发现1 2 3 4 5 6 ... n的排列根据他所给的函数算出来为0.
所以k = 0的时候直接就是1 2 3 4 5 6 ..n
然后前面绝对值是奇数-偶数的绝对值的和,后面是奇数和-偶数和的绝对值
所以我把1 2 3 4 ... n换成 2 1 .... n,前面的和不变为n
后面的和变为n - 2,所以算出来为2,交换一对多2,现在要多2k,交换k对即可
#include <cstdio>
#include <cstring>
const int MAX_NUMBER = 100007;
int n, k;
int main() {
scanf("%d%d", &n, &k);
n *= 2;
k *= 2;
int number = k / 2;
int first = 1;
for (int i = 1; i <= n; i += 2) {
if (number) {
if (first) {
printf("%d %d", i + 1, i);
first = 0;
}
else {
printf(" %d %d", i + 1, i);
}
number--;
}
else {
if (first) {
printf("%d %d", i, i + 1);
first = 0;
}
else {
printf(" %d %d", i, i + 1);
}
}
}
printf("\n");
return 0;
}
3:求最大公约数mod 10^9 + 7
首先用gcd求是肯定不行的,然后发现分母为x ^ (a1 + a2 + ... +an)
分子为x^(a1 + a2 + .. + an-1) + x ^ (a2 + a3 + .. + an) + ....每个x次数为a1 + a2 + ...+ an中去除一项
所以很明显可以约的数一定有x ^ (aa + a2 + a3 + ... + an-1).因为a1,a2,a3...an是递增的,所以a1+a2+a3+..+an-1次数最小
约掉这个公约数是后分母为x^an
分为为 x ^ (an - an) + x^(an - an-1) + x^(an - an-2) + ... + x(an - a1)
然后可能还有公约数x,最小数为x^(an - an),为1,看有多少个1,可能这么多个1加起来还为x的倍数,所以要继续约去x,约去x之后同样多个1加起来仍然和分母x^an有公因数。
一直暴力约去。
AC代码:
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const long long MOD_NUMBER = 1000 * 1000 * 1000 + 7;
const int MAX_NUMBER = 100006;
long long value[MAX_NUMBER];
int vis[MAX_NUMBER];
long long getMod(long long number, long long power) {
if (power == 0) {
return 1;
}
long long x = getMod(number, power / 2);
x = (x * x) % MOD_NUMBER;
if (power % 2) {
x = (x * number) % MOD_NUMBER;
}
return x;
}
long long x, n;
int getPower(int number) {
int i = 1;
while (number % x == 0) {
i++;
number /= x;
}
i--;
return i;
}
int main() {
cin >> n >> x;
memset(vis, 0, sizeof(vis));
long long sums_1 = 0;
for (int i = 1; i <= n; i++) {
cin >> value[i];
if (i != n) {
sums_1 += value[i];
}
}
long long max_n = value[n];
long long ans = getMod(x, sums_1);
int equal = 0;
for (int i = n; i >= 1; i--) {
value[i] = max_n - value[i];
if (value[i] == 0) {
equal++;
vis[i] = 1;
}
}
while ((equal % x) == 0 && max_n > 0) {
ans = (ans * x) % MOD_NUMBER;
equal /= x;
max_n--;
for (int i = 1; i <= n; i++) {
if (!vis[i]) {
value[i]--;
if (value[i] == 0) {
equal++;
vis[i] = 1;
}
}
}
}
cout << ans << endl;
return 0;
}
D:
DP.
left_loc[i]表示value[i]作为约数,最左可以扩展的范围,如果value[i - 1] % value[i] == 0,那么扩展value[i - 1]即可。而value[i - 1]已经向左扩展好了。
同理right_loc[i]。然后求出答案
AC代码:
#include <cstdio>
#include <cstring>
#include <set>
#include <iostream>
using namespace std;
const int MAX_NUMBER = 300006;
int left_loc[MAX_NUMBER];
int right_loc[MAX_NUMBER];
int value[MAX_NUMBER];
int n;
set<int> ans;
int main() {
scanf("%d", &n);
for (int i = 1; i <= n; i++) {
scanf("%d", &value[i]);
}
left_loc[1] = 1;
for (int i = 2; i <= n; i++) {
int j = i;
while (j != 1 && (value[j - 1] % value[i]) == 0) {
j = left_loc[j - 1];
}
left_loc[i] = j;
}
right_loc[n] = n;
for (int i = n - 1; i >= 1; i--) {
int j = i;
while (j != n && (value[j + 1] % value[i]) == 0) {
j = right_loc[j + 1];
}
right_loc[i] = j;
}
int max_number = 0;
ans.clear();
for (int i = 1; i<= n; i++) {
max_number = max(max_number, right_loc[i] - left_loc[i]);
}
for (int i = 1; i <= n; i++) {
if (right_loc[i] - left_loc[i] == max_number) {
ans.insert(left_loc[i]);
}
}
cout << ans.size() << " " << max_number << endl;
for (set<int>::iterator it = ans.begin(); it != ans.end(); it++) {
cout << *it << " ";
}
cout << endl;
}