2018 ICPC Greater New York Regional Contest部分题解

2023-11-09 03:30

本文主要是介绍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=n4a1)那么又因为 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(an1+an2)
然后给出一组任意的 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部分题解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/373826

相关文章

BUUCTF靶场[web][极客大挑战 2019]Http、[HCTF 2018]admin

目录   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 [web][HCTF 2018]admin 考点:弱密码字典爆破 四种方法:   [web][极客大挑战 2019]Http 考点:Referer协议、UA协议、X-Forwarded-For协议 访问环境 老规矩,我们先查看源代码

poj 2976 分数规划二分贪心(部分对总体的贡献度) poj 3111

poj 2976: 题意: 在n场考试中,每场考试共有b题,答对的题目有a题。 允许去掉k场考试,求能达到的最高正确率是多少。 解析: 假设已知准确率为x,则每场考试对于准确率的贡献值为: a - b * x,将贡献值大的排序排在前面舍弃掉后k个。 然后二分x就行了。 代码: #include <iostream>#include <cstdio>#incl

2014 Multi-University Training Contest 8小记

1002 计算几何 最大的速度才可能拥有无限的面积。 最大的速度的点 求凸包, 凸包上的点( 注意不是端点 ) 才拥有无限的面积 注意 :  凸包上如果有重点则不满足。 另外最大的速度为0也不行的。 int cmp(double x){if(fabs(x) < 1e-8) return 0 ;if(x > 0) return 1 ;return -1 ;}struct poin

2014 Multi-University Training Contest 7小记

1003   数学 , 先暴力再解方程。 在b进制下是个2 , 3 位数的 大概是10000进制以上 。这部分解方程 2-10000 直接暴力 typedef long long LL ;LL n ;int ok(int b){LL m = n ;int c ;while(m){c = m % b ;if(c == 3 || c == 4 || c == 5 ||

2014 Multi-University Training Contest 6小记

1003  贪心 对于111...10....000 这样的序列,  a 为1的个数,b为0的个数,易得当 x= a / (a + b) 时 f最小。 讲串分成若干段  1..10..0   ,  1..10..0 ,  要满足x非递减 。  对于 xi > xi+1  这样的合并 即可。 const int maxn = 100008 ;struct Node{int

C++ | Leetcode C++题解之第393题UTF-8编码验证

题目: 题解: class Solution {public:static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num &

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

C - Word Ladder题解

C - Word Ladder 题解 解题思路: 先输入两个字符串S 和t 然后在S和T中寻找有多少个字符不同的个数(也就是需要变换多少次) 开始替换时: tips: 字符串下标以0开始 我们定义两个变量a和b,用于记录当前遍历到的字符 首先是判断:如果这时a已经==b了,那么就跳过,不用管; 如果a大于b的话:那么我们就让s中的第i项替换成b,接着就直接输出S就行了。 这样

笔记整理—内核!启动!—kernel部分(2)从汇编阶段到start_kernel

kernel起始与ENTRY(stext),和uboot一样,都是从汇编阶段开始的,因为对于kernel而言,还没进行栈的维护,所以无法使用c语言。_HEAD定义了后面代码属于段名为.head .text的段。         内核起始部分代码被解压代码调用,前面关于uboot的文章中有提到过(eg:zImage)。uboot启动是无条件的,只要代码的位置对,上电就工作,kern

java线程深度解析(一)——java new 接口?匿名内部类给你答案

http://blog.csdn.net/daybreak1209/article/details/51305477 一、内部类 1、内部类初识 一般,一个类里主要包含类的方法和属性,但在Java中还提出在类中继续定义类(内部类)的概念。 内部类的定义:类的内部定义类 先来看一个实例 [html]  view plain copy pu