题目链接

A - Watching TV

模拟。统计一下哪个数字最多即可。

#include <bits/stdc++.h>
using namespace std; const int maxn = 1e5 + 10; int T, n;
char s[maxn];
int a[maxn]; int main() {
scanf("%d", &T);
while(T --) {
scanf("%d", &n);
memset(a, 0, sizeof a);
for(int i = 1; i <= n; i ++) {
int x;
scanf("%s%d", s, &x);
a[x] ++;
}
int mx = 0;
for(int i = 11111; i <= 99999; i ++) {
mx = max(mx, a[i]);
}
for(int i = 11111; i <= 99999; i ++) {
if(a[i] == mx) {
printf("%d\n", i);
break;
}
}
}
return 0;
}

B - Longest Prefix

模拟。一个串能乱变,一个串不能动,只要统计能变的那个串每个字母有几个即可,到不能动的串上来消耗。

#include <bits/stdc++.h>
using namespace std; const int maxn = 1e5 + 10; int T, n;
char s[maxn], t[maxn];
int cnt[500]; int main() {
scanf("%d", &T);
while(T --) {
memset(cnt, 0, sizeof cnt);
scanf("%s%s", s, t);
int lens = strlen(s);
int lent = strlen(t); for(int i = 0; t[i]; i ++) {
cnt[t[i]] ++;
} int ans = -1;
for(int i = 0; i < lens; i ++) {
if(cnt[s[i]] == 0) break;
ans = i;
cnt[s[i]] --;
}
printf("%d\n", ans + 1); }
return 0;
}

C - Lunch Break

水题。

#include <bits/stdc++.h>
using namespace std; const int maxn = 1e5 + 10; int T, n;
int a, b, c; int main() {
scanf("%d", &T);
while(T --) {
scanf("%d%d%d", &a, &b, &c);
if(a < b && a < c) {
printf("First\n");
}
if(b < a && b < c) {
printf("Second\n");
}
if(c < a && c < b) {
printf("Third\n");
} }
return 0;
}

D - Counting Paths

组合数。通过分析可以发现答案为$2*C_{n - 1}^m$。

#include <iostream>
#include <string.h>
#include <stdio.h> using namespace std;
typedef long long LL; LL n,m;
LL p = 1e9 + 7; const int maxn = 1e5 + 10;
LL f[maxn]; //******************************
//返回d=gcd(a,b);和对应于等式ax+by=d中的x,y
long long extend_gcd(long long a,long long b,long long &x,long long &y)
{
if(a==0&&b==0) return -1;//无最大公约数
if(b==0){x=1;y=0;return a;}
long long d=extend_gcd(b,a%b,y,x);
y-=a/b*x;
return d;
}
//*********求逆元素*******************
//ax = 1(mod n)
long long mod_reverse(long long a,long long n)
{
long long x,y;
long long d=extend_gcd(a,n,x,y);
if(d==1) return (x%n+n)%n;
else return -1;
} LL C(LL n, LL m)
{
long long A = f[n];
long long B = f[n - m] * f[m] % p;
long long C = mod_reverse(B, p);
return A * C % p;
} int main()
{
int T;
f[0] = 1;
for(long long i = 1; i < maxn; i ++) {
f[i] = f[i - 1] * i % p;
}
scanf("%d", &T);
while(T--)
{
scanf("%lld%lld", &n, &m);
if(n == 0) {
printf("0\n");
continue;
}
printf("%lld\n", C(n - 1, m) * 2 % p);
}
return 0;
}

E - Car Factory

水题。

#include <bits/stdc++.h>
using namespace std; const int maxn = 1e5 + 10; int T, n;
char s[maxn], t[maxn];
int cnt[500]; int main() {
scanf("%d", &T);
while(T --) {
long long a, b;
cin >> a >> b;
cout << a + b - 1 << endl; }
return 0;
}

F - Cooking Time

贪心,线段树。如果满了,每次应该扔掉最晚用的那个。

#include <bits/stdc++.h>
using namespace std; const int maxn = 1e5 + 10;
int T, n, k;
int a[maxn], b[maxn], nx[maxn], pos[maxn];
int s[4 * maxn];
int f[maxn]; int lsh(int x) {
int L = 1, R = n;
while(L <= R) {
int mid = (L + R) / 2;
if(b[mid] > x) R = mid - 1;
else if(b[mid] < x) L = mid + 1;
else return mid;
}
return 0;
} void build(int l, int r, int rt) {
s[rt] = 0;
if(l == r) return;
int mid = (l + r) / 2;
build(l, mid, 2 * rt);
build(mid + 1, r, 2 * rt + 1);
} void update(int p, int val, int l, int r, int rt) {
if(l == r) {
s[rt] = val;
return;
}
int mid = (l + r) / 2;
if(p <= mid) update(p, val, l, mid, 2 * rt);
else update(p, val, mid + 1, r, 2 * rt + 1);
s[rt] = max(s[2 * rt], s[2 * rt + 1]);
} int work(int l, int r, int rt) {
if(l == r) return l;
int mid = (l + r) / 2;
if(s[2 * rt] > s[2 * rt + 1]) return work(l, mid, 2 * rt);
else return work(mid + 1, r, 2 * rt + 1);
} int main() {
scanf("%d", &T);
while(T --) {
scanf("%d%d", &n, &k);
for(int i = 1; i <= n; i ++) {
scanf("%d", &a[i]);
b[i] = a[i];
f[i] = 0;
pos[i] = n + 1;
}
sort(b + 1, b + 1 + n);
for(int i = 1; i <= n; i ++) {
a[i] = lsh(a[i]);
}
for(int i = n; i >= 1; i --) {
nx[i] = pos[a[i]];
pos[a[i]] = i;
}
build(1, n, 1);
int ans = 0;
int now = 0;
for(int i = 1; i <= n; i ++) {
if(f[a[i]]) {
update(a[i], nx[i], 1, n, 1);
continue;
}
ans ++;
if(now < k) {
f[a[i]] = 1;
now ++;
update(a[i], nx[i], 1, n, 1);
} else {
int del = work(1, n, 1);
update(del, 0, 1, n, 1);
update(a[i], nx[i], 1, n, 1);
f[del] = 0;
f[a[i]] = 1;
}
}
printf("%d\n", ans);
}
return 0;
}

G - Super Subarray

区间和要能被区间内每个数都整除,就是区间和要能被区间的最小公倍数整除,因此处理出区间的和以及最小公倍数即可,注意爆long long。

#include <bits/stdc++.h>
using namespace std; const int maxn = 2000 + 10;
int T;
int n, k;
long long a[maxn];
long long sum[maxn][maxn];
long long lcm[maxn][maxn];
long long limit = 2000LL * 1e9; long long gcd(long long a, long long b) {
if(b == 0) return a;
return gcd(b, a % b);
} long long LCM(long long a, long long b) {
long long A = a / gcd(a, b);
long long B = b; if(A > limit / B) return -1;
return A * B;
} int main() {
scanf("%d", &T);
while(T --) {
scanf("%d", &n);
for(int i = 1; i <= n; i ++) {
scanf("%lld", &a[i]);
}
int ans = 0;
for(int i = 1; i <= n; i ++) {
for(int j = i; j <= n; j ++) {
sum[i][j] = sum[i][j - 1] + a[j];
if(j == i) lcm[i][j] = a[j];
else lcm[i][j] = LCM(a[j], lcm[i][j - 1]);
if(lcm[i][j] > limit || lcm[i][j] == -1) break;
if(sum[i][j] % lcm[i][j] == 0) ans ++;
}
}
printf("%d\n", ans);
}
return 0;
}

H - Palindrome Number

构造。主要思想是能放$9$就一直放$9$,不能放$9$就放剩余的那个数,注意判断一下不存在的情况。

#include <bits/stdc++.h>
using namespace std; const int maxn = 1e6 + 10;
int T;
int n, s;
int ans[maxn]; int main() {
scanf("%d", &T);
while(T --) {
scanf("%d%d", &n, &s);
if(n % 2 == 0) {
if(s % 2 || s > n * 9) printf("-1\n");
else {
s = s / 2;
for(int i = 0; i < n / 2; i ++) {
if(s >= 9) ans[i] = 9, s -= 9;
else ans[i] = s, s = 0;
}
for(int i = 0; i < n / 2; i ++) {
printf("%d", ans[i]);
}
for(int i = n / 2 - 1; i >= 0; i --) {
printf("%d", ans[i]);
}
printf("\n");
}
} else {
int p = -1;
for(int i = 0; i <= 9; i ++) {
if((s - i) % 2 != 0) continue;
if((s - i) > 9 * (n - 1)) continue;
p = i;
break;
}
if(p == -1) {
printf("-1\n");
continue;
}
s = (s - p) / 2;
for(int i = 0; i < n / 2; i ++) {
if(s >= 9) ans[i] = 9, s -= 9;
else ans[i] = s, s = 0;
}
if(ans[0] == 0) {
printf("-1\n");
continue;
}
for(int i = 0; i < n / 2; i ++) {
printf("%d", ans[i]);
}
printf("%d", p);
for(int i = n / 2 - 1; i >= 0; i --) {
printf("%d", ans[i]);
}
printf("\n");
}
}
return 0;
}

I - Rock Piles

规律。$dp$打表找一下规律就可以了。

#include <bits/stdc++.h>
using namespace std; const int maxn = 1e5 + 10; int T, n, m;
int dp[1010][1010]; void init() {
for(int i = 0; i <= 1000; i ++) {
dp[0][i] = i % 2;
dp[i][0] = i % 2;
}
for(int i = 1; i <= 1000; i ++) {
for(int j = i; j <= 1000; j ++) {
if(dp[i - 1][j] == 0
|| dp[i][j - 1] == 0
|| dp[i - 1][j - 1] == 0) {
dp[i][j] = 1;
dp[j][i] = 1;
} else {
dp[i][j] = 0;
dp[j][i] = 0;
}
}
}
for(int i = 0; i <= 10; i ++) {
for(int j = i; j <= 10; j ++) {
printf("%d %d %d\n", i, j, dp[i][j]);
}
}
} int main() {
// init();
scanf("%d", &T);
while(T --) {
int ans;
scanf("%d%d", &n, &m);
if(n > m) swap(n, m);
if(n % 2) ans = 1;
else ans = m % 2;
if(ans) printf("hasan\n");
else printf("abdullah\n");
}
return 0;
}

J - Spilt the String

暴力。暴力枚举长度,然后验证一下即可。复杂度大约是$O(n*ln(n))$。

#include <bits/stdc++.h>
using namespace std; const int maxn = 1e5 + 10;
int T;
char s[maxn];
int a[maxn];
int L, R; int work(int x) {
int now;
for(now = L + x; now <= R; now += x) {
if(now > R + 1) return 0;
if(now == R + 1) return 1;
if(a[now - 1] == 1 && a[now] == 0) {
while(a[now] == 0) now ++;
}
else return 0;
}
if(now != R + 1) return 0;
return 1;
} int main() {
scanf("%d", &T);
getchar();
while(T --) {
gets(s);
int len = strlen(s);
for(int i = 0; i < len; i ++) {
if(s[i] == ' ') a[i] = 0;
else a[i] = 1;
}
L = 0, R = len - 1;
while(a[L] == 0) L ++;
while(a[R] == 0) R --;
//printf("%d %d\n", L, R);
if(R < L) {
while(1) {}
printf("YES\n");
continue;
}
int ans = 0;
for(int i = 1; i < len; i ++) {
ans = work(i);
// if(ans) printf("debug %d\n", i);
if(ans) break;
}
if(ans) printf("YES\n");
else printf("NO\n");
}
return 0;
}

K - Two Subarrays

$dp$。枚举$i$位置作为分割,那么答案可能是$[1,i]$中的最大值减去$[i + 1,n]$的最小值,也可以反过来。类似于最大子串和的思路可以搞定。

#include <bits/stdc++.h>
using namespace std; const int maxn = 1e5 + 10;
int T, n;
long long a[maxn];
long long L[2][maxn][2];
long long R[2][maxn][2];
long long ll[2][maxn];
long long rr[2][maxn]; int main() {
scanf("%d", &T);
while(T --) {
scanf("%d", &n);
for(int i = 1; i <= n; i ++) {
scanf("%lld", &a[i]);
}
L[0][1][0] = a[1];
L[1][1][0] = a[1];
L[0][2][0] = a[2];
L[0][2][1] = a[1] - a[2];
L[1][2][0] = a[2];
L[1][2][1] = a[1] - a[2];
for(int i = 3; i <= n; i ++) {
/* min */
L[0][i][0] = min(a[i], L[0][i - 1][1] + a[i]);
L[0][i][1] = L[0][i - 1][0] - a[i];
/* max */
L[1][i][0] = max(a[i], L[1][i - 1][1] + a[i]);
L[1][i][1] = L[1][i - 1][0] - a[i];
} R[0][n][0] = a[n];
R[0][n][1] = -a[n];
R[1][n][0] = a[n];
R[1][n][1] = -a[n];
for(int i = n - 1; i >= 1; i --) {
/* min */
R[0][i][0] = min(a[i], a[i] + R[0][i + 1][1]);
R[0][i][1] = min(-a[i], -a[i] + R[0][i + 1][0]);
/* max */
R[1][i][0] = max(a[i], a[i] + R[1][i + 1][1]);
R[1][i][1] = max(-a[i], -a[i] + R[1][i + 1][0]);
} ll[0][1] = a[1];
ll[1][1] = a[1];
for(int i = 2; i <= n; i ++) {
/* min */
ll[0][i] = min(ll[0][i - 1], min(L[0][i][0], L[0][i][1]));
/* max */
ll[1][i] = max(ll[1][i - 1], max(L[1][i][0], L[1][i][1]));
} rr[0][n] = a[n];
rr[1][n] = a[n];
for(int i = n - 1; i >= 1; i --) {
/* min */
rr[0][i] = min(rr[0][i + 1], R[0][i][0]);
/* max */
rr[1][i] = max(rr[1][i + 1], R[1][i][0]);
} long long ans = 0;
for(int i = 2; i <= n; i ++) {
ans = max(ans, abs(ll[0][i - 1] - rr[1][i]));
ans = max(ans, abs(ll[1][i - 1] - rr[0][i]));
}
printf("%lld\n", ans);
}
return 0;
}

L - The Shortest Path

$spfa$。某点入队超过$n$次就表示存在负环。某点最短路小于图中所有负边权之和,也说明存在负环。

#include <bits/stdc++.h>
using namespace std; const long long INF = 1LL * 6000 * 1e6;
const int maxn = 1e5 + 10;
int T, n, m;
int h[maxn], v[maxn], nx[maxn];
long long w[maxn];
int sz;
long long dis[maxn];
int f[maxn], cnt[maxn];
long long g[2100][2100];
long long sum;
long long ans; void add(int a, int b, long long c) {
v[sz] = b;
w[sz] = c;
nx[sz] = h[a];
h[a] = sz ++;
} void spfa() {
int fail = 0;
for(int i = 0; i <= n; i ++) {
dis[i] = INF;
f[i] = 0;
cnt[i] = 0;
}
queue<int> q;
dis[0] = 0;
f[0] = 1;
q.push(0);
while(!q.empty()) {
int first = q.front();
q.pop();
f[first] = 0;
cnt[first] ++;
if(cnt[first] == n + 1) {
fail = 1;
break;
}
if(dis[first] < sum) {
fail = 1;
break;
}
for(int i = h[first]; i != -1; i = nx[i]) {
if(dis[first] + w[i] < dis[v[i]]) {
dis[v[i]] = dis[first] + w[i];
if(f[v[i]] == 0) {
f[v[i]] = 1;
q.push(v[i]);
}
}
}
}
if(fail) {
printf("-inf\n");
} else {
long long mn = INF;
for(int i = 1; i <= n; i ++) {
mn = min(mn, dis[i]);
}
if(mn == 0) printf("%lld\n", ans);
else printf("%lld\n", min(ans, mn));
}
} int main() {
scanf("%d", &T);
while(T --) {
scanf("%d%d", &n, &m);
for(int i = 0; i <= n; i ++) {
h[i] = -1;
}
sz = 0;
for(int i = 0; i <= n; i ++) {
for(int j = 0; j <= n; j ++) {
g[i][j] = INF;
}
}
for(int i = 1; i <= m; i ++) {
int a, b;
long long c;
scanf("%d%d%lld", &a, &b, &c);
g[a][b] = min(c, g[a][b]);
}
sum = 0;
ans = INF;
for(int i = 1; i <= n; i ++) {
for(int j = 1; j <= n; j ++) {
if(g[i][j] == INF) continue;
add(i, j, g[i][j]);
ans = min(ans, g[i][j]);
if(g[i][j] < 0) sum += g[i][j];
}
}
for(int i = 1; i <= n; i ++) {
add(0, i, 0);
}
spfa();
}
return 0;
}

M - Restore Points

暴力。将$d$数组排序,那么最右边的那个点的坐标肯定是$d$数组最后一个值,然后枚举$d$数组倒数第二个值是放在靠左还是靠右,一直枚举下去即可。

#include <bits/stdc++.h>
using namespace std; const int maxn = 1e6 + 10;
int T, n, m;
int d[maxn];
int ans[maxn];
int p[maxn];
int suc; void dfs(int x, int y) {
if(x == n) {
int ok = 1;
for(int i = 0; i < m; i ++) {
if(p[d[i]]) ok = 0;
}
if(ok) suc = 1;
return;
}
if(p[d[y]] == 0) {
dfs(x, y - 1);
return;
}
for(int t = 0; t < 2; t ++) {
int fail = 0;
if(t == 0) ans[x] = d[y];
else ans[x] = ans[1] - d[y];
for(int i = 0; i < x; i ++) {
if(p[abs(ans[x] - ans[i])] == 0) {
fail = 1;
}
}
if(fail) continue;
for(int i = 0; i < x; i ++) {
p[abs(ans[x] - ans[i])] --;
}
dfs(x + 1, y - 1);
if(suc) return;
for(int i = 0; i < x; i ++) {
p[abs(ans[x] - ans[i])] ++;
}
}
} int main() {
scanf("%d", &T);
while(T --) {
scanf("%d", &n);
m = n * (n - 1) / 2;
for(int i = 0; i < m; i ++) {
scanf("%d", &d[i]);
p[d[i]] ++;
}
sort(d, d + m);
ans[0] = 0;
ans[1] = d[m - 1];
p[ans[1]] --;
suc = 0;
dfs(2, m - 2);
sort(ans, ans + n);
for(int i = 0; i < n; i ++) {
printf("%d", ans[i]);
if(i < n - 1) printf(" ");
else printf("\n");
}
for(int i = 0; i < m; i ++) {
if(p[d[i]]) {
while(1) {}
}
}
}
return 0;
}

2017 ACM Amman Collegiate Programming Contest 题解的更多相关文章

  1. 2017 ACM Amman Collegiate Programming Contest

    A - Watching TV /* 题意:求出出现次数最多的数字 */ #include <cstdio> #include <algorithm> #include < ...

  2. 2015 ACM Amman Collegiate Programming Contest 题解

    [题目链接] A - Who Is The Winner 模拟. #include <bits/stdc++.h> using namespace std; int T; int n; s ...

  3. 18春季训练01-3/11 2015 ACM Amman Collegiate Programming Contest

    Solved A Gym 100712A Who Is The Winner Solved B Gym 100712B Rock-Paper-Scissors Solved C Gym 100712C ...

  4. 2017 ACM Arabella Collegiate Programming Contest div2的题,部分题目写个题解

    F. Monkeying Around   维护点在多少个线段上 http://codeforces.com/gym/101350/problem/F 题意:有m个笑话,每个笑话的区间是[L, R], ...

  5. 2017 ACM Arabella Collegiate Programming Contest(solved 11/13)

    省选考前单挑做点ACM练练细节还是很不错的嘛- 福利:http://codeforces.com/gym/101350 先来放上惨不忍睹的virtual participate成绩(中间跑去食堂吃饭于 ...

  6. ACM Amman Collegiate Programming Contest(7.22随机组队娱乐赛)

    题目链接 https://vjudge.net/contest/240074#overview 只写一下自己做的几个题吧 /* D n^2的暴力dp怎么搞都可以的 这里先预处理 i到j的串时候合法 转 ...

  7. Codeforces 2016 ACM Amman Collegiate Programming Contest B. The Little Match Girl(贪心)

    传送门 Description Using at most 7 matchsticks, you can draw any of the 10 digits as in the following p ...

  8. Codeforces 2016 ACM Amman Collegiate Programming Contest A. Coins(动态规划/01背包变形)

    传送门 Description Hasan and Bahosain want to buy a new video game, they want to share the expenses. Ha ...

  9. Gym 101102A Coins -- 2016 ACM Amman Collegiate Programming Contest(01背包变形)

    A - Coins Time Limit:3000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Descript ...

随机推荐

  1. alertdialog 设置最大高度

    设置最大高度,有很多方法,我个人比较喜欢的是下面这种方式 ,这里的view即添加到 view.addOnLayoutChangeListener(new View.OnLayoutChangeList ...

  2. [译]Quartz.NET 框架 教程(中文版)2.2.x 之第六课 CronTrigger

    第六课 CronTrigger CronTrigger比SimpleTrigger更常用,当你需要一个基于日历般概念的作业调度器,而不是像SimpleTrigger那样精确指定间隔时间. 使用Simp ...

  3. python 三种遍历列表里面序号和值的方法

    list = ['html', 'js', 'css', 'python'] # 方法1 # 遍历列表方法1:' for i in list: print("序号:%s 值:%s" ...

  4. 【BZOJ】3160: 万径人踪灭 FFT+回文串

    [题意]给定只含'a'和'b'字符串S,求不全连续的回文子序列数.n<=10^5. [算法]FFT+回文串 [题解]不全连续的回文子序列数=回文子序列总数-回文子串数. 回文子串数可以用回文串算 ...

  5. 【转】C#中PrintDocument类详解

    PrintDocument组件是用于完成打印的类,其常用属性.方法和事件如下: 属性DocumentName:字符串类型,记录打印文档时显示的文档名(例如,在打印状态对话框或打印机队列中显示). 方法 ...

  6. HDU 1427 速算24点 (深搜)

    题目链接 Problem Description 速算24点相信绝大多数人都玩过.就是随机给你四张牌,包括A(1),2,3,4,5,6,7,8,9,10,J(11),Q(12),K(13).要求只用' ...

  7. git之合并分支(git merge)------(三)

    最近几天写小demo,总是自己拉取他人的代码,然后创建分支,在自己的分支上进行修改,然后提交到自己的分支,具体的这一步,我就不多讲了,因为在我的博客“工作中常用的Git操作”中有详细的介绍,今天主要讲 ...

  8. 初时Python博大精深

    Python是解释型语言 编译型vs解释型 编译型优点:编译器一般会有预编译的过程对代码进行优化.因为编译只做一次,运行时不需要编译,所以编译型语言的程序执行效率高.可以脱离语言环境独立运行.缺点:编 ...

  9. CSS line-height与行内框

    一.line-height的定义 line-height,行高,是指文本行基线间的垂直距离. 1.    什么是基线? 一般而言,一个文本行一共有四条线,从上到下依次为顶线.中线.基线.底线:在英文中 ...

  10. 20155303 2016-2017-2 《Java程序设计》第一周学习总结

    20155303 2016-2017-2 <Java程序设计>第一周学习总结 教材学习内容总结 浏览教材,根据自己的理解每章提出一个问题 Chapter1 Java平台概论:MyProgr ...