比赛时候卡在全场题L,心态很崩,后来其他题目思考不进去了。。。加上一个队友临时有事也没来训练。。。最后4题收尾。。。

补题补题,现在把暂时都切出来的题目放上题解和代码吧~

------------------------------------------------------------------------------------------------------------------

A:题意是只能对第一堆的土进行移动,求花费代价最小。

贪心求解,O(n)复杂度

首先让c[i] = a[i]-b[i],那么显然c[i]>0意味着第i号位置的土比较多,应该从c[i]>0的位置往c[j]<0的位置移动

用一个指针记录最左端c[i]>0的位置,现在应该用最靠左的土填满当前c[i]<0的位置,然后扫描一遍就A了~

代码如下:

#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;const int maxn = 1e5+10;
int a[maxn],b[maxn],c[maxn];
int n;
typedef long long LL;inline int Min(int x, int y) {return x<y?x:y; }
inline int Max(int x, int y) {return x>y?x:y; }int main(){int T;scanf("%d",&T);while (T--){scanf("%d",&n);for (int i=1; i<=n; i++) scanf("%d",&a[i]);for (int i=1; i<=n; i++) scanf("%d",&b[i]);for (int i=1; i<=n; i++) c[i] = a[i] - b[i];LL ans = 0;int idx = 1;for (int i=1; i<=n; i++) if (c[i]<0) {while (c[i]<0) {while (idx<=n && c[idx]<=0) idx++;int t = Min(-c[i],c[idx]);ans += (LL)t*abs(i-idx);c[i] += t; c[idx] -= t;}}printf("%lld\n",ans);}return 0;
}

B:对于当前节点i,i*F(i) 相当于累加F(i)个i,F(i)是第i个节点有的合约数节点个数。

那么只要把i加到每个合约数节点后再统计即可。

说的有点不清楚,看代码里面的dfs就能懂的~

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;typedef long long LL;
const int mod = 1e9+7;
const int maxn = 2e4+10;
vector<int>g[maxn];
vector<int>vec[maxn];
bool vis[maxn];
int w[maxn];
int n,p;LL cnt[maxn];
LL ans;void init(){for (int i=1; i<=10000; i++) vis[i] = 1;for (int i=2; i<=10000; i++) if (vis[i]) {for (int j=i+i; j<=10000; j+=i) vis[j] = 0;}for (int i=2; i<=10000; i++) if (vis[i]==0) {for (int j=i; j<=10000; j+=i) vec[j].push_back(i);}
}void dfs(int u, int fa) {int v;for (int i=0; i<vec[w[u]].size(); i++) {v = vec[w[u]][i];cnt[v] = (cnt[v] + u + mod)%mod;}ans = (ans+cnt[w[u]])%mod;for (int i=0; i<g[u].size(); i++) {if (g[u][i] == fa) continue;dfs(g[u][i],u);}for (int i=0; i<vec[w[u]].size(); i++) {v = vec[w[u]][i];cnt[v] = (cnt[v] - u + mod)%mod;}
}int main(){//freopen("in.txt","r",stdin);int T;scanf("%d",&T);init();while (T--) {ans = 0;scanf("%d%d",&n,&p);for (int i=1; i<=n; i++) g[i].clear();for (int i=1; i<=n; i++) cnt[i] = 0;int v,u;for (int i=1; i<n; i++) {scanf("%d%d",&u,&v);g[u].push_back(v);g[v].push_back(u);}for (int i=1; i<=n; i++) scanf("%d",&w[i]);dfs(p,-1);printf("%lld\n",ans);}return 0;
}

C:n<=9,利用STL的next_permutation枚举全排列,然后统计转换次数

可以预处理a[i]转换为b[j]需要的操作次数,简单题

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;const int maxn = 20;
const int INF = 1e9;
int a[maxn],b[maxn],p[maxn];
int cost[maxn][maxn];
int n;int calc(int x, int y) {if (x == y) return 0;if (x < y) swap(x,y);int res = 0;while (x>y) {if (x%2 == 0) {if (x/2>=y) { x>>=1; res++; }else {res += x-y; return res; }}else {--x;res++;}}return res;
}int t[maxn];
int solve(){memcpy(t,p,sizeof(t));int res = 0;for (int i=1; i<=n; i++) {if (t[i] != i) {for (int j=i+1; j<=n; j++) if (t[j] == i) {swap(t[j],t[i]);break;}res++;}}return res;
}int main(){int T;scanf("%d",&T);while (T--){scanf("%d",&n);for (int i=1; i<=n; i++) scanf("%d",&a[i]);for (int j=1; j<=n; j++) scanf("%d",&b[j]);for (int i=1; i<=n; i++) p[i] = i;for (int i=1; i<=n; i++)for (int j=1; j<=n; j++) cost[i][j] = calc(a[i],b[j]);int ans = INF;do {int f = 0;for (int i=1; i<=n; i++) f += cost[p[i]][i];f += solve();if (f<ans) ans = f;}while (next_permutation(p+1,p+n+1));printf("%d\n",ans);}return 0;
}

D: 这题个人认为很难,无法证明结论,但写起来就几行代码。。

#include <cstdio>
using namespace std;int L1,R1,L2,R2,mod;
int main(){int T;scanf("%d",&T);while (T--) {scanf("%d%d%d%d%d",&L1,&R1,&L2,&R2,&mod);if (R2-L2+1>=mod) printf("LOSE\n");else printf("WIN\n");}return 0;
}

E:签到题~

#include <cstdio>
#include <map>
using namespace std;typedef long long LL;
LL ans,n;int main(){while (scanf("%lld",&n)==1){ans = (LL)1<<n;printf("%lld\n",ans);}return 0;
}

F:找规律题,可以发现满足要求的x转换为二进制后,不会有相邻两位都为1

假设当前枚举的二进制长度为x,满足题意的数字个数为f(x),能发现f(x)是斐波那契数列~

代码如下:

#include <cstdio>
#include <cstring>
using namespace std;const int maxn = 70;
typedef long long LL;
LL f[maxn],sum[maxn];
LL n;void init(){f[0] = f[1] = 1;for (int i=2; i<=60; i++) f[i] = f[i-1] + f[i-2];sum[0] = 1;for (int i=1; i<=60; i++) sum[i] = sum[i-1] + f[i];
}int main(){init();//freopen("in.txt","r",stdin);int T;scanf("%d",&T);while (T--){scanf("%lld",&n);LL ans = 0;bool isfirst = 1;while (n>0) {if (isfirst) {if (n == 1) {ans = 1LL;break;}int i=0;while (sum[i]<n) i++;ans += 1LL<<i;n -= sum[i-1];isfirst = 0;}else {n = n-1;int i = 0;if ( n == 1) {ans = ans+1;break;} else if ( n == 0) {break;}while (sum[i]<n) i++;ans += 1LL<<i;n -= sum[i-1];}}printf("%lld\n",ans);}return 0;
}

G:待填坑

H:待填坑

I:签到题,不过不知道为什么官方题解那么说那么多。。。

也不理解为什么要用java或python写大数。。

很显然的,找到最高位奇数,然后修改就可以了。

假设字符串长度为n,最高奇数为在第i位。

1:第i位数字为9,把第i位数字减一,i+1到n位数字全部变为8

2:看第i位之后的数字是否都是4 或出现 若干个4然后接着一个比4小的数字,是的话第i位数字减一,后面i+1到n位全部为8

3:以上两种情况不满足,把第i位数字加一,后面全部变为0

代码如下:

#include <cstdio>
#include <cstring>
using namespace std;const int maxn = 100000+10;
char s[maxn];
int n;int main(){int T;scanf("%d",&T);while (T--){scanf("%s",s);n = strlen(s);int st = 0;while (st<n && (s[st]-'0')%2==0 ) st++;if (st>=n) {printf("%s\n",s);continue;}if (n == 1 && s[0] == '1') {printf("0\n");continue;}int nxt = st+1;while (nxt<n && s[nxt]=='4') nxt++;if (nxt>=n || s[nxt]<'4' || s[st]=='9') {s[st]--;for (int i=st+1; i<n; i++) s[i] = '8';}else {s[st]++;for (int i=st+1; i<n; i++) s[i] = '0';}int f = 0; while (f<n && s[f]=='0') f++;for (int i=f; i<n; i++) printf("%c",s[i]); printf("\n");}return 0;
}

J:二分+二分图最大匹配

最多N+1个空位,m个点向可以插入的空连边。有n+1-m个虚点,向|ai-1 - ai| <= len 的空连边 ,结果要求完全匹配~

代码如下:

#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;const int INF = 1e9+7;
const int maxn = 200+10;
int n,m;
int a[maxn],b[maxn];
int g[maxn][maxn];
int left[maxn];
bool vis[maxn];bool match(int u) {for (int i=1; i<=m; i++) if (g[i][u] && !vis[i]) {vis[i] = 1;if (!left[i] || match(left[i])) {left[i] = u;return 1;}}return 0;
}bool judge(int mid) {for (int i=1; i<=m; i++) {for (int j=1; j<=n+1; j++) {g[i][j] = 1;if (j>1 && abs(b[i]-a[j-1])>mid) g[i][j] = 0;if (j<n+1 && abs(b[i]-a[j])>mid) g[i][j] = 0;}}int ans = 0;for (int i=1; i<=n+1; i++) left[i] = 0;for (int i=2; i<=n; i++) {if (abs(a[i-1]-a[i])>mid) {for (int j=1; j<=m; j++) vis[j] = 0;if (!match(i)) return 0;ans++;}}for (int i=1; i<=n+1; i++) {if (i==1 || i==n+1 || abs(a[i-1]-a[i])<=mid) {for (int j=1; j<=m; j++) vis[j] = 0;ans += match(i);}}return ans == m;
}int main(){int T;scanf("%d",&T);while (T--){scanf("%d%d",&n,&m);for (int i=1; i<=n; i++) scanf("%d",&a[i]);for (int j=1; j<=m; j++) scanf("%d",&b[j]);int left = 0, right = INF;int mid, ans = 0;while (left <= right) {mid = (left+right)>>1;if (judge(mid)) {right = mid-1;ans = mid;}else left = mid+1;}printf("%d\n",ans);}return 0;
}

K:待填坑

L:这题卡了N久,最后还没写出来,太菜了。。。据说出题人搞错了,数据当成连续子串也A了。。。

emmm,正解DP我还没想出来,平时练习DP太少了。。

先放上一个有毛病的AC代码,当成连续子串处理的。

#include <cstdio>
using namespace std;typedef long long LL;
const int maxn = 1e5+10;
int a[maxn];
LL sum[maxn];
int n,k;inline int Max(int x, int y) {return x>y?x:y; }
int main(){while (scanf("%d%d",&n,&k) == 2) {for (int i=1; i<=n; i++) {scanf("%d",&a[i]);a[i] %= k;}sum[0] = 0;for (int i=1; i<=n; i++) sum[i] = sum[i-1] + a[i];int mx = -1;for (int i=1; i<=n; i++) {for (int j=n; j>=i; j--) if ((sum[j]-sum[i-1])%k == 0) {mx = Max(mx,j-i+1);break;}}printf("%d\n",mx);}return 0;
}

埃森哲杯上海大学春季赛暨金马五校赛题解汇总相关推荐

  1. 第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛 个人笔记 题解

    题目链接:https://ac.nowcoder.com/acm/contest/90#question A.跳台阶 链接:https://ac.nowcoder.com/acm/contest/90 ...

  2. 【牛客网】埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 题解

    题目连接 A.Wasserstein Distance (水题) 题意:给你2行土a,b,每行都有n堆,每堆对应有a[i],b[i]克,我们可以对a中的土进行移动,移动任意堆的k克泥土到a中其他堆消耗 ...

  3. 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 L-K序列

    埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 L-K序列 链接:https://www.nowcoder.com/acm/contest/91/L 来源:牛客网 题目描述 给一个数组 ...

  4. 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 A-Wasserstein Distance

    埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 A-Wasserstein Distance 链接:https://www.nowcoder.com/acm/contest/91/A ...

  5. 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 E-小Y吃苹果

    埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 E-小Y吃苹果 链接:https://www.nowcoder.com/acm/contest/91/E 来源:牛客网 题目描述 小Y买 ...

  6. 好久没撸c,第一场回状态的题(埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛

    题目链接: 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛 A:Wasserstein Distance ## 题意:有2大堆柱状图的土(总体积相同,问从第一堆土移动到第二堆消耗最少的 ...

  7. 第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛 K-密码

    第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛 K-密码 链接:https://www.nowcoder.com/acm/contest/90/K 来源:牛客网 题目描述 ZiZi登录各种账号的 ...

  8. 第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛 I-填空题

    第13届景驰-埃森哲杯广东工业大学ACM程序设计大赛 I-填空题 链接:https://www.nowcoder.com/acm/contest/90/I 来源:牛客网 题目描述 牛客网是是一个专注于 ...

  9. 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛B合约数

    链接:https://www.nowcoder.com/acm/contest/91/B 来源:牛客网 题目描述 在埃森哲,员工培训是最看重的内容,最近一年,我们投入了 9.41 亿美元用于员工培训和 ...

最新文章

  1. SRM598 Div1
  2. ZZULIOJ 1918: G 【二分图匹配】
  3. arc 和 非arc兼容
  4. ubuntu19.10安装deepin的微信和qq(转载+自己在新系统上验证)
  5. .Net 分布式云平台基础服务建设说明概要
  6. 麦森数(洛谷P1045题题解,Java语言描述)
  7. clickhouse 获取几天前的日期
  8. Android 记住账号密码+自动登录
  9. Excel Access 新建空白文档/打开已有文档 提示内存或磁盘空间不足的解决方法--验证...
  10. linux下RRDTool安装方法
  11. webpack5+vue3搭建h5项目模板-(一)-基础配置
  12. 查看linux系统语言并修改
  13. 是如何通过阿里面试的?
  14. 【QT开发笔记-基础篇】| 第五章 绘图QPainter | 5.1 效果演示、技术点
  15. vue 网页滚动到指定位置显示动画效果
  16. 高分辨率对地观测系统重大科技专项简介
  17. cas55266-17-6四羧基苯基卟啉铁简称TCPP-Fe(3+)齐岳定制β-硝基-5, 10,15, 20-四苯基卟啉镍[NiTPP(NO2)]供应卟啉定制产品
  18. 串口实现PC之间传输文件
  19. IOS下使用GSOAP(客户端)
  20. 【彻底解决】谷歌或Edge浏览器登录谷歌账户提示浏览器不安全请重新登录

热门文章

  1. 打标签的U盘,win10不认服务未开启
  2. stm32f103系列开发板控制对数码管来显示自定义时间(自主学习)
  3. iOS UITextView自动识别链接(自动识别URL)
  4. 分析Android引起的“电视智能化”之TV用UI的现状与未来
  5. Exchange问题处理:Exchange server OAB 脱机地址簿下载失败常见解决方法
  6. 【Algorithm】Prim
  7. R语言时间序列分析之ARIMA模型预测
  8. STM32F407ZG 检测环境温度 CubeIDE
  9. 朋友圈都在说的央行数字货币,究竟跟你有什么关系
  10. 【OBS】解决OBS推两个rtmp流 + 带时间戳问题