本文主要是介绍2018 ICPC Greater New York Regional Contest部分题解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
原题地址:https://www.jisuanke.com/contest/1857?view=challenges&tdsourcetag=s_pcqq_aiomsg
PS:AC代码AC自CSUOJ,在计蒜客上有些题可能会有点格式问题
文章目录
- A. Potato Sacks
- C .Hedwig's Ladder
- E.What time is it anyway?
- G.The Erdös-Straus Conjecture
- H.Subprime Fibonacci Sequence
A. Potato Sacks
题意:给出一个背包的大小,然后给出n个物品,问你能否用这k个物品装满背包.
思路:签到题,01背包。
#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
int T;
int a[maxn];
int dp[20][200];
int main() {scanf("%d", &T);while (T--) {CLR(dp, 0);int id;scanf("%d", &id);int w;scanf("%d", &w);for (int i = 1; i <= 10; i++) {scanf("%d", &a[i]);}for (int i = 1; i <= 10; i++) {for (int j = a[i]; j <= w; j++) {dp[i][j] = max(dp[i-1][j], dp[i - 1][j - a[i]] + a[i]);}}printf("%d ", id);if (dp[10][w] == w) printf("YES\n");else printf("NO\n");}return 0;
}/**********************************************************************Problem: 2270User: yiqzqLanguage: C++Result: ACTime:4 msMemory:2428 kb
**********************************************************************/
C .Hedwig’s Ladder
题意:给你一个如题目描述的图,然后给出你可以走的步数,每次你从左上角出发,要求同一个点之只能经过一次,问你有几种走法。
思路:暴力打表题,然后找规律。
我们对当前的图进行建图,然后跑dfs记录数据即可。
最后可以发现,结果类似与一个斐波那契数列,只不过奇数位要再加个1。
#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 10007;
struct node {int v, nxt;
} e[maxn];
int head[maxn], tot;
void add_edge(int u, int v) {e[tot].v = v;e[tot].nxt = head[u];head[u] = tot++;e[tot].v = u;e[tot].nxt = head[v];head[v] = tot++;
}
int ans = 0;
int vis[maxn];
void dfs(int u, int num) {if (num == 0) {ans++;return;}vis[u] = 1;for (int i = head[u]; ~i; i = e[i].nxt) {int v = e[i].v;if (vis[v]) continue;vis[v] = 1;dfs(v, num - 1);vis[v] = 0;}
}
ll fac[maxn];
int main() {
// int MAX = 40;
// CLR(head, -1);
// for (int i = 1; i <= MAX - 1; i++) {
// add_edge(i, i + 1);
// }
// for (int i = MAX + 1; i <= 2 * MAX - 1; i++) {
// add_edge(i, i + 1);
// }
// for (int i = 1; i <= MAX; i++) {
// add_edge(i, i + MAX);
// }
// for (int i = 1; i <= 30; i++) {
// ans = 0;
// CLR(vis, 0);
// dfs(1, i);
// printf("i=%d %d\n", i, ans);
// }fac[1] = 2;fac[2] = 3;for (int i = 3; i <= 1004; i++) {fac[i] = fac[i - 1] + fac[i - 2];if (i % 2) fac[i]++;fac[i] %= mod;}int T;scanf("%d", &T);while (T--) {int id;scanf("%d", &id);int x;scanf("%d", &x);printf("%d %lld\n", id, fac[x]);}return 0;
}/**********************************************************************Problem: 2272User: yiqzqLanguage: C++Result: ACTime:0 msMemory:4368 kb
**********************************************************************/
E.What time is it anyway?
题意:有n个时钟,还有n个时差,现在你需要确定一个具体时间,满足n个时钟每个都对应着一个时差。
思路:模拟题,难点在于对时间加法的写法。
PS :要注意时钟的的进位,且正确时间要用set去存,因为可能存在有多种答案,但是答案都是一样的情况。
#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 100;
const int mod = 1e9 + 7;
int T, id, n;struct node {int h, m, flag;//flag判断是一个时差是一个正数还是负数node() {h = 0, m = 0;}node(int h, int m): h(h), m(m) {}node(int h, int m, int flag): h(h), m(m), flag(flag) {}bool operator < (const node &a)const {return h < a.h || (h == a.h && m < a.m);}node operator + (const node &a)const {//+右边是时差node exa;if (a.flag)exa.h = h + a.h;else exa.h = h - a.h;if (a.flag)exa.m = m + a.m;else exa.m = m - a.m;if (exa.m >= 60) {exa.m -= 60;exa.h++;} else if (exa.m < 0) {exa.m += 60;exa.h--;}if (exa.h > 12)exa.h -= 12;else if (exa.h < 1) exa.h += 12;return exa;}node operator - (const node &a)const {//+右边是时差node exa;if (a.flag)exa.h = h - a.h;else exa.h = h + a.h;if (a.flag)exa.m = m - a.m;else exa.m = m + a.m;if (exa.m >= 60) {exa.m -= 60;exa.h++;} else if (exa.m < 0) {exa.m += 60;exa.h--;}if (exa.h > 12)exa.h -= 12;else if (exa.h < 1) exa.h += 12;return exa;}
} tim[maxn], lag[maxn], correct, ans;
map<node, int>mp;
int cnt = 0;
set<node>S;
void init() {//初始化时钟mp.clear();for (int i = 1; i <= n; i++) {mp[tim[i]]++;}
}
void check(node correct) {//判断当前时间是否可行解for (int i = 2; i <= n; i++) {node t = correct - lag[i];if (mp[t]) mp[t]--;} else return ;}ans = correct;S.insert(correct);
}
int main() {scanf("%d", &T);while (T--) {S.clear();CLR(lag, 0);CLR(tim, 0);scanf("%d%d", &id, &n);for (int i = 1; i <= n; i++) {scanf("%d:%d", &tim[i].h, &tim[i].m);}for (int i = 1; i <= n; i++) {char a[20];char flag;scanf("%s", a + 1);sscanf(a + 1, "%c%d:%d", &flag, &lag[i].h, &lag[i].m);lag[i].h %= 12;if (flag == '+') lag[i].flag = 0;//要和题目数据改成反的else lag[i].flag = 1;}cnt = 0;for (int i = 1; i <= n; i++) {//枚举n种正确解释init();correct = tim[i] + lag[1];mp[tim[i]]--;check(correct);}printf("%d ", id);int cnt = S.size();if (cnt == 1) {printf("%d:%02d\n", ans.h, ans.m);} else if (cnt >= 2) printf("%d\n", cnt);else printf("none\n");}return 0;
}
G.The Erdös-Straus Conjecture
题意:给出一个 n n n,满足式子 4 n = 1 a + 1 b + 1 c \frac{4}{n}=\frac{1}{a}+\frac{1}{b}+\frac{1}{c} n4=a1+b1+c1,求满足条件的 a , b , c a,b,c a,b,c,且 a , b , c a,b,c a,b,c的字典序是要最小的。
思路:
通过暴力打表前几项,我们发现 a a a的值都是 n / 4 + 1 n/4+1 n/4+1,所以猜测a的值是 n / 4 + 1 n/4+1 n/4+1,(PS:但是不解的是 a a a的范围应该是 [ n / 4 + 1 , n / 4 + 3 ] [n/4+1,n/4+3] [n/4+1,n/4+3], 然后假设我们已知了正确的 a a a,(令 x y = 4 n − 1 a \frac{x}{y}=\frac{4}{n}-\frac{1}{a} yx=n4−a1)那么又因为 a , b , c a,b,c a,b,c是按照字典序排序的,所以显然 b b b的范围是 [ y x + 1 , 2 y x ] [\frac{y}{x}+1,\frac{2y}{x}] [xy+1,x2y](取两个极端, 1 b = 1 c \frac{1}{b}=\frac{1}{c} b1=c1或者 1 c = 0 \frac{1}{c}=0 c1=0),最后 c c c的值就由验算得来。
#include<iostream>
#include<algorithm>
#include<vector>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<ctime>
#define fuck(x) cout<<#x<<" = "<<x<<endl;
#define ls (t<<1)
#define rs ((t<<1)+1)
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 100086;
const int inf = 2.1e9;
const ll Inf = 999999999999999999;
const int mod = 1000000007;
const double eps = 1e-6;
const double pi = acos(-1);ll cal(ll n, ll b, ll x, ll y) {ll y1 = b * y;ll x1 = x * b - y;if (x1 == 0) {return -1;}if (y1 % x1 == 0) {return y1 / x1;} else return -1;
}int main() {int T;scanf("%d", &T);while (T--) {int id;scanf("%d", &id);ll n;scanf("%lld", &n);int flag = 0;for (ll a = n / 4 + 1; a <= n / 4 + 3; a++) {ll x = 4 * a - n;ll y = a * n;for (ll i = y / x + 1 ; i <= 2 * y / x; i++) {ll t = cal(n, i, x, y);if (t > 0) {printf("%d %lld %lld %lld\n",id, a, i, t);flag = 1;break;}}if (flag) break;}}return 0;
}
H.Subprime Fibonacci Sequence
题意:定义一种新的运算 S P ( x ) , SP(x), SP(x),当 x x x为质数或者 1 1 1的时候,返回 x x x,否则返回 p x \frac{p}{x} xp( p p p是最小的能被 x x x整除的质数)。然后定义 a n = S P ( a n − 1 + a n − 2 ) a_n=SP(a_{n-1}+a_{n-2}) an=SP(an−1+an−2)。
然后给出一组任意的 a 0 a_0 a0和 a 1 a_1 a1,让你输出是否存在循环节,如果存在,输出循环节位置和循环节长度,并输出循环节。
思路:先打出质数表。然后由于n的范围只有1000,所以我们可以暴力算出a数组。然后由于这个a数组的每一个值只与前两个有关,因此只要有两个数字连续重复,那就肯定会出现循环节了。所以我们可以利用map存取两个数字的复合值,对于遍历到的每一个数,查询map中是否出现过这个数字。然后记录长度和起始位置就行了。
#include <bits/stdc++.h>
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 1e9 + 7;
int noprime[maxn * 10], pcnt, p[maxn * 10]; //p存的是质数
void getprime(int N) {pcnt = 0;memset(noprime, 0, sizeof(noprime));//0表示是质数noprime[0] = noprime[1] = 1;for (int i = 2; i < N; ++i) {if (!noprime[i]) {p[pcnt++] = i;//p是存的所有质数}for (int j = 0; j < pcnt && i * p[j] < N; ++j) {noprime[i * p[j]] = 1;if (i % p[j] == 0)break;}}
}
int SP(int x) {if (x == 1 || noprime[x] == 0) return x;for (int i = 0; i < pcnt; i++) {if (x % p[i] == 0) return x / p[i];}
}
int a[maxn];
int T, id, n;
map<int, int>mp;
int main() {getprime(maxn);scanf("%d", &T);while (T--) {mp.clear();int len = -1, index = -1;scanf("%d%d", &id, &n);scanf("%d%d", &a[1], &a[2]);printf("%d", id);for (int i = 3; i <= 3000; i++) {a[i] = SP(a[i - 1] + a[i - 2]);}for (int i = 1; i <= n - 1; i++) {int num = a[i] * 1000000 + a[i + 1];if (mp[num]) {index = i;len = i - mp[num];break;}mp[num] = i;}if (index != -1) {printf(" %d %d\n", index, len);for (int i = index, j = 1; i <= len + index + 1; i++, j++) {printf("%d", a[i]);if (j % 20 == 0 || i == len + index + 1) printf("\n");else printf(" ");}} else {printf(" %d 0\n%d\n", n, a[n + 1]);}}return 0;
}
/**********************************************************************Problem: 2277User: yiqzqLanguage: C++Result: ACTime:140 msMemory:10232 kb
**********************************************************************/
这篇关于2018 ICPC Greater New York Regional Contest部分题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!