2018 Multi-University Training Contest 4
Contents
- Problem A. Integers Exhibition
- Problem B. Harvest of Apples
- Problem C. Problems on a Tree
- Problem D. Nothing is Impossible
- Problem E. Matrix from Arrays
- Problem F. Travel Through Time
- Problem G. Depth-First Search
- Problem H. Eat Cards, Have Fun
- Problem I. Delightful Formulas
- Problem J. Let Sudoku Rotate
- Problem K. Expression in Memories
- Problem L. Graph Theory Homework
Problem A. Integers Exhibition
留坑。
Problem B. Harvest of Apples
题意:
计算
思路:
由
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll MOD = 1e9 + 7;
const int maxn = 1e5 + 10;
int unit;
ll inv[maxn];
ll invfac[maxn];
ll fac[maxn];
ll ans[maxn];
int n, m;
struct node {
int l, r, id;
inline node() {}
inline node(int l, int r, int id) : l(l), r(r), id(id) {}
inline bool operator<(const node &b) const {
if (l / unit != b.l / unit)
return l / unit < b.l / unit;
else
return r < b.r;
}
} arr[maxn];
inline void Init() {
fac[0] = invfac[0] = 1;
fac[1] = inv[1] = invfac[1] = 1;
for (int i = 2; i < maxn; ++i) {
fac[i] = fac[i - 1] * i % MOD;
inv[i] = inv[MOD % i] * (MOD - MOD / i) % MOD;
invfac[i] = invfac[i - 1] * inv[i] % MOD;
}
}
inline ll cal(int a, int b) {
ll res = fac[a] * invfac[b] % MOD * invfac[a - b] % MOD;
return res;
}
inline void work() {
ll tmp = 0;
for (int i = 0; i <= arr[1].r; ++i) {
tmp = (tmp + cal(arr[1].l, i)) % MOD;
}
ans[arr[1].id] = tmp;
int L = arr[1].l, R = arr[1].r;
for (int i = 2; i <= n; ++i) {
while (L < arr[i].l) {
tmp = (tmp * 2 % MOD - cal(L++, R) + MOD) % MOD;
}
while (L > arr[i].l) {
tmp = (tmp + cal(--L, R) + MOD) % MOD * inv[2] % MOD;
}
while (R < arr[i].r) {
tmp = (tmp + cal(L, ++R)) % MOD;
}
while (R > arr[i].r) {
tmp = (tmp - cal(L, R--) + MOD) % MOD;
}
ans[arr[i].id] = tmp;
}
}
int main() {
Init();
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d %d", &arr[i].l, &arr[i].r);
arr[i].id = i;
}
unit = (int)sqrt(n);
sort(arr + 1, arr + 1 + n);
work();
for (int i = 1; i <= n; ++i) {
printf("%lld\n", ans[i]);
}
return 0;
}
Problem C. Problems on a Tree
留坑。
Problem D. Nothing is Impossible
题意:
给出
一共有
思路:
排序,前缀积。
Code
#include <bits/stdc++.h>
using namespace std;
#define N 110
#define ll long long
struct node {
int a, b, sum;
inline void scan() {
scanf("%d%d", &a, &b);
sum = a + b;
}
inline bool operator<(const node &r) const {
return sum < r.sum;
}
} arr[N];
int t, n, m;
ll sum;
int main() {
scanf("%d", &t);
while (t--) {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) arr[i].scan();
sort(arr + 1, arr + 1 + n);
int ans = 0;
sum = 1;
for (int i = 1; i <= n; ++i) {
sum *= arr[i].sum;
if (sum > m)
break;
ans = i;
}
printf("%d\n", ans);
}
return 0;
}
Problem E. Matrix from Arrays
题意:
给出一种构造二维数组的构造方式,然后给出一个左上角,一个右下角,求这个矩形内的数和。
思路:
打表找规律发现,大矩阵是由若干个
Code
#include <bits/stdc++.h>
using namespace std;
#define N 110
typedef long long ll;
int n;
int x[2], y[2];
ll arr[N];
ll G[N][N];
inline ll cal(int x, int y) {
if (x < 0 || y < 0)
return 0ll;
ll res = G[n - 1][n - 1] * (x / n) * (y / n) + G[n - 1][y % n] * (x / n) + G[x % n][n - 1] * (y / n) +
G[x % n][y % n];
return res;
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = 0; i < n; ++i) {
scanf("%lld", arr + i);
}
for (int i = 0, cnt = 0; i < (n << 2); ++i) {
for (int j = 0; j <= i; ++j) {
G[j][i - j] = arr[cnt];
cnt = (cnt + 1) % n;
}
}
n <<= 1;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < n; ++j) {
G[i][j] += (i ? G[i - 1][j] : 0);
G[i][j] += (j ? G[i][j - 1] : 0);
G[i][j] -= ((i && j) ? G[i - 1][j - 1] : 0);
}
}
int q;
scanf("%d", &q);
while (q--) {
scanf("%d %d %d %d", &x[0], &y[0], &x[1], &y[1]);
ll ans = cal(x[1], y[1]) - cal(x[0] - 1, y[1]) - cal(x[1], y[0] - 1) + cal(x[0] - 1, y[0] - 1);
printf("%lld\n", ans);
}
}
return 0;
}
Code
#include <bits/stdc++.h>
using namespace std;
#define N 1100
#define ll long long
int t, n, q, x[2], y[2];
ll arr[N];
ll G[N][N];
int main() {
scanf("%d", &t);
while (t--) {
scanf("%d", &n);
for (int i = 1; i <= n; ++i) scanf("%lld", arr + i);
memset(G, 0, sizeof G);
for (int i = 0, cnt = 0; i <= (n << 2); ++i) {
for (int j = 0; j <= i; ++j) {
G[j][i - j] = arr[cnt + 1];
cnt = (cnt + 1) % n;
}
}
n <<= 1;
ll base = 0;
for (int i = 0; i < n; ++i)
for (int j = 0; j < n; ++j) base += G[i][j];
scanf("%d", &q);
while (q--) {
scanf("%d%d%d%d", &x[0], &y[0], &x[1], &y[1]);
ll ans = 0, tmp;
// compute Big
ll xl = (x[1] - x[0] + 1) / n, yl = (y[1] - y[0] + 1) / n;
ans += (base * xl * yl);
// compute lower_left corner
tmp = 0;
for (int i = x[0] + xl * n; i <= x[1]; ++i) {
for (int j = y[0], cnt = 1; cnt <= n; ++cnt, ++j) tmp += G[i % n][j % n];
}
// compute upper_right corner
ans += tmp * yl;
tmp = 0;
for (int i = x[0], cnt = 1; cnt <= n; ++cnt, ++i) {
for (int j = y[0] + yl * n; j <= y[1]; ++j) tmp += G[i % n][j % n];
}
// compute lower_right corner
ans += tmp * xl;
tmp = 0;
for (int i = x[0] + xl * n; i <= x[1]; ++i) {
for (int j = y[0] + yl * n; j <= y[1]; ++j) ans += G[i % n][j % n];
}
printf("%lld\n", ans);
}
}
return 0;
}
Problem F. Travel Through Time
留坑。
Problem G. Depth-First Search
留坑。
Problem H. Eat Cards, Have Fun
留坑。
Problem I. Delightful Formulas
留坑。
Problem J. Let Sudoku Rotate
题意:
给出一个
思路:
爆搜,两条剪枝,一个是判断是否有冲突,一个是判断当前步数是否比已有答案大。
Code
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e2 + 10;
int ans;
bool vis[20];
char s[20];
int G[maxn][maxn];
inline bool judge(int x, int y) {
for (int i = x * 4 - 3; i <= x * 4; ++i) {
memset(vis, false, sizeof vis);
for (int j = 1; j <= y * 4; ++j) {
if (vis[G[i][j]])
return false;
vis[G[i][j]] = true;
}
}
for (int i = y * 4 - 3; i <= y * 4; ++i) {
memset(vis, false, sizeof vis);
for (int j = 1; j <= x * 4; ++j) {
if (vis[G[j][i]])
return false;
vis[G[j][i]] = true;
}
}
return true;
}
inline void fun(int x, int y) {
int tmp[10][10];
for (int i = 1; i <= 4; ++i) {
for (int j = 1; j <= 4; ++j) {
tmp[j][4 - i + 1] = G[(x - 1) * 4 + i][(y - 1) * 4 + j];
}
}
for (int i = 1; i <= 4; ++i) {
for (int j = 1; j <= 4; ++j) {
G[(x - 1) * 4 + i][(y - 1) * 4 + j] = tmp[i][j];
}
}
}
inline void DFS(int x, int y, int res) {
if (res >= ans)
return;
if (y > 4) {
DFS(x + 1, 1, res);
return;
}
if (x == 5) {
ans = min(ans, res);
return;
}
for (int i = 0; i < 4; ++i) {
if (i) {
fun(x, y);
/* if(x == 3 && y == 1 && i == 1)
{
for(int i = x * 4 - 3; i <= x * 4; ++i)
{
for(int j = y * 4 - 3; j <= y * 4; ++j)
{
printf("%d%c", G[i][j], " \n"[j == y * 4]);
}
}
}*/
}
if (judge(x, y)) {
DFS(x, y + 1, res + i);
}
}
fun(x, y);
}
int main() {
int t;
scanf("%d", &t);
while (t--) {
ans = 1 << 16;
for (int i = 1; i <= 16; ++i) {
scanf("%s", s + 1);
for (int j = 1; j <= 16; ++j) {
if (s[j] >= '0' && s[j] <= '9') {
G[i][j] = s[j] - '0';
} else if (s[j] >= 'A' && s[j] <= 'F') {
G[i][j] = (s[j] - 'A') + 10;
}
}
}
// fun(1, 1);
DFS(1, 1, 0);
printf("%d\n", ans);
}
return 0;
}
Problem K. Expression in Memories
按题意模拟即可
Code
#include <bits/stdc++.h>
using namespace std;
#define N 100010
int t;
char s[N];
int main() {
scanf("%d", &t);
while (t--) {
scanf("%s", s);
bool flag = true;
int len = strlen(s);
for (int i = 0; i < len; ++i) {
if (s[i] == '*' || s[i] == '+') {
if (i == 0 || i == len - 1) {
flag = false;
break;
} else if (s[i + 1] == '*' || s[i + 1] == '+') {
flag = false;
break;
}
} else if (s[i] == '0') {
if (i == 0 || s[i - 1] == '*' || s[i - 1] == '+') {
if (i + 1 < len && s[i + 1] >= '0' && s[i + 1] <= '9') {
flag = false;
break;
} else if (s[i + 1] == '?')
s[i + 1] = '+';
}
} else if (s[i] == '?') {
s[i] = '1';
}
}
if (flag) {
printf("%s\n", s);
} else {
printf("IMPOSSIBLE\n");
}
}
return 0;
}
Problem L. Graph Theory Homework
水。
Code
Last update: March 28, 2022
Created: March 28, 2022
Created: March 28, 2022