今天还是很有必要总结一下牛客网上的 埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛。
今天发挥失常,仅出了5题,rank100+。
比赛:埃森哲杯第十六届上海大学程序设计联赛春季赛暨上海高校金马五校赛
形式:团队赛
队伍出题:5/12
个人出题:2
A:搬沙子使两堆沙子每部分数量一样,求最小步数。很简单的想到如果第一堆沙子多于第二堆就把第一堆多出来的往后搬一格,第二堆多就把第二堆多的往后搬一格。相等就不搬,累加搬得总数量就是答案。然而不要忘了用long long,否则就只能过52%(不要问我怎么知道的,我不知道)
B:这样的题目用到一些思维,比赛时候没做出来有点可惜,不过也算是一种提高,有必要详细说一下。
链接:https://www.nowcoder.com/acm/contest/91/B
来源:牛客网
合约数
时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
在埃森哲,员工培训是最看重的内容,最近一年,我们投入了 9.41 亿美元用于员工培训和职业发展。截至 2018 财年末,我们会在全球范围内设立 100 所互联课堂,将互动科技与创新内容有机结合起来。按岗培训,按需定制,随时随地,本土化,区域化,虚拟化的培训会让你快速取得成长。小埃希望能通过培训学习更多ACM 相关的知识,他在培训中碰到了这样一个问题,
给定一棵n个节点的树,并且根节点的编号为p,第i个节点有属性值val
i, 定义F(i): 在以i为根的子树中,属性值是val
i的合约数的节点个数。y 是 x 的合约数是指 y 是合数且 y 是 x 的约数。小埃想知道
对1000000007取模后的结果.
输入描述:
输入测试组数T,每组数据,输入n+1行整数,第一行为n和p,1<=n<=20000, 1<=p<=n, 接下来n-1行,每行两个整数u和v,表示u和v之间有一条边。第n+1行输入n个整数val1, val2,…, valn,其中1<=vali<=10000,1<=i<=n.
输出描述:
对于每组数据,输出一行,包含1个整数, 表示对1000000007取模后的结果
我的题解怎么没了???
写了几十行 一发表就没了什么鬼???写了两遍还是没了。。。坑死我了。。。今天CSDN有毒
AC代码:
#include<bits/stdc++.h> #define lson l,mid,t<<1 #define rson mid+1,r,t<<1|1 #define ll long long using namespace std; const int maxn=20010; const int N=20010; const int mo=1e9+7; int m,k,x,y,p; int n,num; int ans,tmp; bool us[maxn]; int flag; int a[maxn],f[maxn],bing[maxn]; int z[maxn],b[maxn],he[maxn]; bool jd[maxn]; vector<int>vc[maxn]; void add(int u,int v) { vc[u].push_back(v); } void init() { int mx=10001; memset(b,0,sizeof(b)); int i=2,j=2; for(i=2;i<mx;i++) { for(j=2;j*i<mx;j++) { b[i*j]=1; } } } void quyu(int &x){x%=p;if(x<0)x+=p;} void dfs(int x,int fa) { quyu(f[a[x]]+=x); if(b[a[x]]) for(int i=a[x];i<maxn;i+=a[x]) quyu(ans+=f[i]); us[x]=1; for(int i=0;i<vc[x].size();i++) { int v=vc[x][i]; if(!us[v]&&v!=fa) { dfs(v,x); } } us[x]=0; quyu(f[a[x]]-=x); } int main() { int T; init(); scanf("%d",&T); while(T--){ memset(bing,0,sizeof(bing)); memset(he,-1,sizeof(he)); memset(us,0,sizeof(us)); memset(f,0,sizeof(f)); scanf("%d %d",&n,&m); num=0; p=mo; for(int i=1;i<maxn;i++) vc[i].clear(); for(int i=0;i<n-1;i++) { int u,v; scanf("%d %d",&u,&v); add(u,v); add(v,u); } for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } ans=0; dfs(m,-1); printf("%d\n",ans); } //(flag) puts("Yes");else puts("No"); return 0; } /* 2 5 4 5 3 2 5 4 2 1 3 10 4 3 10 5 3 3 1 3 2 1 1 10 1 */I:
链接:
https://www.nowcoder.com/acm/contest/91/I
来源:牛客网
二数
来源:牛客网
二数
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
空间限制:C/C++ 131072K,其他语言262144K
64bit IO Format: %lld
题目描述
我们把十进制下每一位都是偶数的数字叫做“二数”。
小埃表示自己很聪明,最近他不仅能够从小数到大:2,3,4,5....,也学会了从大数到小:100,99,98...,他想知道从一个数开始数最少的数就得到一个二数。但是聪明的小森已经偷偷在心里算好了小埃会数到哪个二数,请你求出他要数到哪个数吧。
换句话说,给定一个十进制下最多10 5位的数字,请你求出和这个数字的差的绝对值最小的二数,若答案不唯一,输出最小的那个。
换句话说,给定一个十进制下最多10 5位的数字,请你求出和这个数字的差的绝对值最小的二数,若答案不唯一,输出最小的那个。
也就是说,给定数字n,求出m,使得abs(n-m)最小且m[i] mod 2 = 0
输入描述:
1 ≤ T ≤ 100, 1 ≤ n ≤ 10100000 − 1, T组数据的数字的十进制表示长度总和不超过1000000
输出描述:
每行一个整数 m 第 i 行表示第 i 个数所对应的“最邻近二数”
AC代码:
#include<bits/stdc++.h> #define lson l,mid,t<<1 #define rson mid+1,r,t<<1|1 #define ll long long using namespace std; const int maxn=1000010; const int mo=1e12; int m,k,x,y; int cnt,n; char ans[maxn],tmp[maxn]; int flag; char s[maxn]; int main() { int T; scanf("%d",&T); while(T--){ scanf("%s",s); int l=strlen(s); int mi=-1,ma=-1; for(int i=0;i<l;i++) { int id=(s[i]&15); if(id&1) {mi=i;break;} tmp[i]=s[i]; ans[i]=s[i]; } if(mi==-1) {printf("%s\n",s);continue;} int qian=0; int hou=0; if(s[mi]!='9') { tmp[mi]=(s[mi]+1); ans[mi]=(s[mi]-1); int t=(s[mi]&15)*10; int f=(tmp[mi]&15)*10; int g=(ans[mi]&15)*10; int i=mi+1; while(i<l) { int id=t+(s[i]&15); if(abs(f-id)>abs(id-g-8)&&!qian&&!hou) {qian=1;} else if(abs(f-id)<abs(id-g-8)&&!qian&&!hou) {hou=1;} else {f=(tmp[mi]&15)*10;g=(ans[mi]&15)*10;;} tmp[i]='0'; ans[i]='8'; i++; } } else { qian=1; ans[mi]=(s[mi]-1); int i=mi+1; while(i<l) { ans[i]='8'; i++; } } ans[l]='\0';tmp[l]='\0'; if(qian||(qian==0&&hou==0)) { int i=0; while(ans[i]=='0'&&i<l-1) i++; printf("%s\n",ans+i); } else { int j=0; while(tmp[j]=='0'&&j<l-1) j++; printf("%s\n",tmp+j); } } return 0; }