2017 Multi-University Training Contest
来源:互联网 发布:国产电视机 知乎 编辑:程序博客网 时间:2024/06/10 14:02
补题补题
Is Derek lying?
题意:
Derek和Alfia分别做题,题目选项有A、B、C,现在他们所选的选项和所得的分告诉你,问他们有没有撒谎。思路:判定他们的上下限即可,当D和A有一个人全对时,他们一样的肯定得分,不一样的肯定不得分,假设一样的选项为k个,不一样的为p个,那么他们总分之和一定小于k * 2 + p,两分之差肯定小于p。
#include <bits/stdc++.h>#define MAXN 800050using namespace std;int main() { int T, n, x, y; char ch1[MAXN], ch2[MAXN]; scanf("%d", &T); while (T--) { scanf("%d %d %d", &n, &x, &y); getchar(); gets(ch1); gets(ch2); if (x > n || y > n || x < 0 || y < 0) { puts("Lying"); continue; } int k = 0; for (int i = 0; i < n; i++) { if (ch1[i] == ch2[i]) { k++; } } int t1 = min(x, y); int t2 = max(x, y); int p = t2 - t1, m = n - k; if (p <= m && t1 + t2 <= 2 * k + m) { puts("Not lying"); } else { puts("Lying"); } }}
Maximum Sequence
题意:
给一个序列ai,每次可以从b数组里任意选数表示可以从下标为1到n(这里的n,每次制造出来一个新的数n会增长)的数中任意选取一个数下标为j制造出一个数放置在a序列最后面,这个数的值为aj - j,现在问新制造出来的数的和最大是多少。
思路:
拿个优先队列维护一下可用值。
所给的b序列贪心每次取最小的即可。
#include <bits/stdc++.h>#define MAXN 500050#define ll long long#define MOD 1000000007using namespace std;struct node { ll idx, val; bool operator < (const node &a) const { return val < a.val; }};priority_queue<node> q;ll num[MAXN];void init() { while (!q.empty()) { q.pop(); }}int main() { ll n, tmp; while (~scanf("%lld", &n)) { init(); for (ll i = 0; i < n; i++) { scanf("%lld", &tmp); q.push((node){i + 1, tmp - (i + 1)}); } for (ll i = 0; i < n; i++) { scanf("%lld", &num[i]); } sort(num, num + n); ll ans = 0; for (ll i = 0; i < n; i++) { while (!q.empty() && q.top().idx < num[i]) { q.pop(); } ans += q.top().val; ans %= MOD; ll tt = q.top().val; q.push((node){n + i + 1, tt - (n + i + 1)}); } printf("%lld\n", ans); } }
Sdjpx Is Happy
题意:
给一个序列,你可以将这个序列分成任意块,每一个块可以随意排序,你可以将其中两个块换一次位置。
现在问你最多可以分成多少块思路:
先暴力预处理将每个区间内,可分成块的个数处理出来,若区间最大值和最小值不等于区间长度,则为0,若相对于上一块区间出现了新的最小值,则只为1,因为只能排序不能在这个区间内再分块。
若没制造出新的,则可以等于上一个区间与该区间的块状和。
然后再枚举每一块区间,若满足区间内可拆,则枚举拆点将其拆开(因为有一次交换机会)。有点像dp。。但是就是区间暴力枚举
#include <bits/stdc++.h>#define MAXN 3010#define ll long longusing namespace std;int mn[MAXN][MAXN], mx[MAXN][MAXN];int sum[MAXN][MAXN];int a[MAXN], la[MAXN];int main() { int T, n; scanf("%d", &T); while (T--) { scanf("%d", &n); memset(sum, 0, sizeof(sum)); for (int i = 1; i <= n; i++) { scanf("%d", &a[i]); mn[i][i] = mx[i][i] = a[i]; sum[i][i] = 1; la[i] = i; } for (int i = 1; i <= n; i++) { for (int j = i + 1; j <= n; j++) { mn[i][j] = min(mn[i][j - 1], a[j]); mx[i][j] = max(mx[i][j - 1], a[j]); } } for (int i = 2; i <= n; i++) { for (int j = 1; j + i - 1 <= n; j++) { int e = i + j - 1; if (mx[j][e] - mn[j][e] != e - j) { sum[j][e] = 0; } else { if (mn[j][e] < mn[j][la[j]]) { sum[j][e] = 1; } else { sum[j][e] = sum[j][la[j]] + sum[la[j] + 1][e]; } la[j] = e; } } } int ans = sum[1][n]; for (int i = 1; i <= n; i++) { for (int j = i; j <= n; j++) { if (sum[i][j] && (i == 1 || (sum[1][i - 1] && mn[1][i - 1] == 1))) { int p = mx[i][j]; if (p == n || (sum[p + 1][n] && mx[p + 1][n] == n)) { for (int k = p; k > j; k--) { if (sum[k][p] && mn[k][p] == i) { ans = max(ans, sum[1][i - 1] + sum[j + 1][k - 1] + sum[p + 1][n] + 2); } } } } } } printf("%d\n", ans); } return 0;}
Funny Function
题意:有三个算式现在让你求F
m,1 思路:
赛后跟机智的队友补题,暴力打表把10x10的数据打了出来。。竟然发现了规律对于偶数
每行有f(n, m) = f(n - 2, 2) * (2n - 1)m−1
每列有f(n, 2) = f(n - 2,2) * 4 + 2对于奇数
每行有f(n, m) = f(n - 2, 2) * (2n - 1)m−1
每列有f(n, 2) = f(n - 2,2) * 4 + 1当n或者m为1时,都为1。
然后矩阵快速幂和快速幂求解即可。。
#include <bits/stdc++.h>#define N 2#define ll long long#define MOD 1000000007using namespace std;struct mat{ ll mapp[N][N];};mat res;ll rec[] = {2, 5};void output(mat a) { printf("=======\n"); for (int i = 0; i < N; i++) { for (int j = 0; j < N; j++) { printf("%lld ", a.mapp[i][j]); } puts(""); }}ll update(ll a) { while (a < 0) { a += MOD; } return a;}mat mul_mat(mat a, mat b, ll mod, int p) { mat c;// output(a);// puts("-----");// output(b); for (int i = 0; i < N; i++) { for (int j = 0; j < p; j++) { c.mapp[i][j] = 0; for (int k = 0; k < N; k++) { c.mapp[i][j] = update(c.mapp[i][j]); c.mapp[i][j] += (a.mapp[i][k] * b.mapp[k][j]) % mod; c.mapp[i][j] %= mod; } } } return c;}mat ksm_mat(mat n, ll k, ll mod, int p) { mat t = n, ans = res; while (k) { if (k & 1) { ans = mul_mat(t, ans, mod, p); } t = mul_mat(t, t, mod, 2); k >>= 1; } return ans;}ll ksm(ll n, ll k, ll mod) { ll temp = n, ans = 1; while (k) { if (k & 1) { ans = update(ans); ans = (ans * temp) % mod; } k >>= 1; temp = (temp * temp) % mod; } return ans % mod;}ll get(ll n, ll opt) { mat p = {4, 1, 0, 1}; if (opt) { //偶数 res = (mat){rec[0], 0, 2, 0}; } else { res = (mat){rec[1], 0, 1, 0}; } mat ans = ksm_mat(p, n, MOD, 1); return ans.mapp[0][0];}ll getAns(ll n, ll m) { if (n == 1 || m == 1) { return 1; } ll ans; if (n & 1) { ll a = get(n / 2 - 1, 0); ll b = get(n / 2 - 1, 1); res = (mat){a, 0, -b, 0}; mat p = (mat){ksm(2, n, MOD) - 1, 1, 0, 1};// output(p); ans = ksm_mat(p, m - 2, MOD, 1).mapp[0][0]; } else { ans = (get(n / 2 - 1, 1) * ksm(((ksm(2, n, MOD) - 1 + MOD) % MOD), m - 2, MOD)) % MOD; } ans = update(ans); return ans;}int main() { int T; ll n, m; scanf("%d", &T); while (T--) { scanf("%lld %lld", &n, &m); printf("%lld\n", getAns(n, m)); }}
TrickGCD
题意:
给一个序列,对于序列的每个数,你可以取1-ai中的任意数,现在让你组成新的序列,问可以组成多少个满足每个区间都满足gcd >= 2。思路:
用筛法每次枚举每个除数,算区间内的可以被除的数的情况,最后再容斥一下把多余的去掉即可。
#include <iostream>#include <vector>#include <map>#include <cstdlib>#include <stdio.h> #include <string.h>#define MAX_PRIME 200000#define ll long long#define MAXN 100005#define MOD 1000000007using namespace std;ll f[MAXN];ll sum[MAXN];void init() { memset(sum, 0, sizeof(sum)); for (ll i = 0; i < MAXN; i++) { f[i] = 1; }}ll ksm(ll a, ll n) { ll ans = 1, t = a; while (n) { if (n & 1) { ans = (ans * t) % MOD; } t = (t * t) % MOD; n >>= 1; } return ans;}int main(){ ll T, n, c, cas = 1; while (~scanf("%lld", &T)) { while (T--) { init(); ll lastans = 0; scanf("%lld", &n); for (ll i = 0; i < n; i++) { scanf("%lld", &c); sum[c]++; } for (ll i = 1; i < MAXN; i++) { sum[i] += sum[i - 1]; } for (ll i = 2; i < MAXN; i++) { if (sum[i - 1]) { f[i] = 0; continue; } for (ll j = i; j < MAXN; j += i) { ll k = min(i + j - 1, (ll)(MAXN) - 1); ll b = sum[k] - sum[j - 1]; ll a = j / i; f[i] = (f[i] * ksm(a, b)) % MOD; } } for (ll i = MAXN - 1; i >= 2; i--) { for (ll j = i * 2; j <= MAXN; j += i) { f[i] = (f[i] - f[j] + MOD) % MOD; } } for (ll i = 2; i < MAXN; i++) { lastans = (lastans + f[i]) % MOD; } printf("Case #%lld: %lld\n", cas++, lastans); } }}
Regular polygon
题意:
一个200x200的坐标上有n个点整数点。问能组成多少个不同的正多边形。题解:
其实题意都是废话。。求正多边形。其实就只有正方形的存在。。
直接判每四个点存不存在就好了。
(orz hdu卡精度搞到写个cos和sin都给卡了。。)
#include <stdio.h>#include <math.h>#include <string.h>#define MAXN 1005using namespace std;const double PI = acos(-1.0);bool mapp[MAXN][MAXN];struct point { int x, y; } p[MAXN];point xuanzhuan(point a, point b) { point c; c.x = -(a.y - b.y) + b.x; c.y = a.x - b.x + b.y; return c;}int solve(point a, point b) { for (int i = 0; i < 4; i++) { point c = xuanzhuan(a, b); a = b; b = c; if (c.x < MAXN && c.x >= 0 && c.y < MAXN && c.y >= 0) { if (!mapp[c.x][c.y]) { return 0; } } else { return 0; } } return 1;}int main() { int n, ans; while (~scanf("%d", &n)) { ans = 0; memset(mapp, false, sizeof(mapp)); for (int i = 0; i < n; i++) { scanf("%d %d", &p[i].x, &p[i].y); p[i].x += 200; p[i].y += 200; mapp[p[i].x][p[i].y] = true; } for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (i != j) { ans += solve(p[i], p[j]); } } } printf("%d\n", ans / 4); }} /*90 00 11 01 12 00 22 22 44 2*/
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- #2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- #2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- 2017 Multi-University Training Contest
- UVA
- 斜率优化DP
- 我的进步
- CGI与FastCGI的介绍
- 【POJ3744】Scout YYF I
- 2017 Multi-University Training Contest
- SAMBA服务器笔记
- ArrayList集合数据排序问题
- DOM(一)
- 理解C中复杂声明
- python多线程学习(续)
- 杭电ACM求和小问题
- tinyXml和stl中map使用的一点坑
- Garland(CodeForces