AtCoder diverta 2019 Programming Contest 2

看起来我也不知道是一个啥比赛。

然后就写写题解QWQ。

A - Ball Distribution

有\(n\)个气球\(k\)个人,每个人至少要拿一个气球。问所有分配方案中拿走气球最多的那个人可以比最少的那个人多拿多少个。

打比赛的时候一开始没看到题,别人说输出\(n\% k\)就过了,然后我就过了。

现在重新一看题解。。。

应该是\(k=1\)时,答案是\(0\),否则答案是\(n-k\)。

  1. #include<iostream>
  2. #include<cstdio>
  3. using namespace std;
  4. inline int read()
  5. {
  6. int x=0;bool t=false;char ch=getchar();
  7. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  8. if(ch=='-')t=true,ch=getchar();
  9. while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
  10. return t?-x:x;
  11. }
  12. int main()
  13. {
  14. int n=read(),k=read();
  15. if(k==1)puts("0");
  16. else printf("%d\n",n-k);
  17. return 0;
  18. }

B - Picking Up

平面上有若干个点,你可以任意指定两个数\(p,d\)。

你现在要依次选定所有点,如果在选定某个点\((x,y)\)之前,存在点\((x-p,y-d)\)已经被选中了,那么代价就是\(0\),否则代价是\(1\)。

求出选定所有点的最小代价。

不难想到\(p,d\)已经是某两个点的坐标的差,那么枚举一下,钦定\(p\)为正数,然后按照\(x\)从小往大排序,如果一样就按\(y\)排序,依次选中就行了。如果\(p=0\),就钦定\(d>0\)就行了。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<set>
  5. using namespace std;
  6. #define MAX 55
  7. inline int read()
  8. {
  9. int x=0;bool t=false;char ch=getchar();
  10. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  11. if(ch=='-')t=true,ch=getchar();
  12. while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
  13. return t?-x:x;
  14. }
  15. int n;
  16. struct Node{int x,y;}p[MAX];
  17. bool operator<(Node a,Node b){if(a.x!=b.x)return a.x<b.x;return a.y<b.y;}
  18. set<Node> M;
  19. int ans=1e9;
  20. int main()
  21. {
  22. n=read();
  23. for(int i=1;i<=n;++i)p[i].x=read(),p[i].y=read();
  24. if(n==1){puts("1");return 0;}
  25. sort(&p[1],&p[n+1]);
  26. for(int i=1;i<=n;++i)
  27. for(int j=1;j<=n;++j)
  28. {
  29. int P=p[j].x-p[i].x,Q=p[j].y-p[i].y;
  30. if(P<0)P=-P,Q=-Q;
  31. M.clear();int ret=0;
  32. for(int k=1;k<=n;++k)
  33. {
  34. if(!M.count((Node){p[k].x-P,p[k].y-Q}))++ret;
  35. M.insert(p[k]);
  36. }
  37. ans=min(ans,ret);
  38. }
  39. printf("%d\n",ans);
  40. return 0;
  41. }

C - Successive Subtraction

有\(n\)个数,执行下列操作\(n-1\)次:选定两个数\(a,b\),删去它们,并把\(a-b\)加入进来

问最后剩下的数的最大值,并且构造一种方案。

首先如果我们把操作画成树型结构,左儿子等价于\(+1\),右儿子等价于\(-1\),那么每个数的贡献就是到根节点的路径的乘积乘上自身的权值。

因为至少进行一次操作,所以至少一个数不能变号,至少一个数必须变号,其他数任意。

所以把所有数排序之后,最大值钦定不变号,最小值钦定变号,其他数如果是负数就变号,否则不变号。

构造方案的话,除了最大值和最小值之外,用最小值减去不变号的数,用最大值减去要变号的数,再用最大值减去最小值就行了。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. #include<vector>
  5. using namespace std;
  6. #define ll long long
  7. #define MAX 100100
  8. inline int read()
  9. {
  10. int x=0;bool t=false;char ch=getchar();
  11. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  12. if(ch=='-')t=true,ch=getchar();
  13. while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
  14. return t?-x:x;
  15. }
  16. int n,a[MAX],b[MAX],s;
  17. vector<pair<int,int> > T;
  18. int main()
  19. {
  20. n=read();
  21. for(int i=1;i<=n;++i)a[i]=read();
  22. sort(&a[1],&a[n+1]);
  23. for(int i=2;i<n;++i)b[i]=a[i]<0;
  24. b[1]=1;b[n]=0;
  25. for(int i=2;i<n;++i)
  26. if(b[i])T.push_back(make_pair(a[n],a[i])),a[n]-=a[i];
  27. else T.push_back(make_pair(a[1],a[i])),a[1]-=a[i];
  28. T.push_back(make_pair(a[n],a[1]));
  29. printf("%d\n",a[n]-a[1]);
  30. for(auto a:T)printf("%d %d\n",a.first,a.second);
  31. return 0;
  32. }

D - Squirrel Merchant

你一开始有\(n\)块钱,有两家商店\(A,B\)。

你可以在两家商店把签换成金银铜或者把金银铜换成钱,并且在同一家商店用钱换一单位金银铜和一单位金银铜换钱的钱的数量是一样的。

现在你会先去\(A\)再去\(B\)再去\(A\)然后回家。

问回家后你最多有多少钱。

所有数字\(\le 5000\)

首先如果只先去\(A\)再去\(B\),那么做一个\(dp\)。设\(f[i]\)表示在\(A\)花了\(i\)块钱换东西,到了\(B\)之后最多能够卖的钱数。

这样子我们就知道了到了\(B\)之后我们有多少钱。

而这个钱数不会超过\(N*5000\),而\(5000*5000\)的数组是能够开下的,所以就再\(dp\)一次就做完了。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. using namespace std;
  5. #define ll long long
  6. #define MAX 25000100
  7. inline ll read()
  8. {
  9. ll x=0;bool t=false;char ch=getchar();
  10. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  11. if(ch=='-')t=true,ch=getchar();
  12. while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
  13. return t?-x:x;
  14. }
  15. ll f[MAX],n,gA,sA,bA,gB,sB,bB;
  16. int main()
  17. {
  18. n=read();
  19. gA=read();sA=read();bA=read();
  20. gB=read();sB=read();bB=read();
  21. for(int i=0;i<=n;++i)
  22. {
  23. if(i+gA<=n&&gA<gB)f[i+gA]=max(f[i+gA],f[i]+gB);
  24. if(i+sA<=n&&sA<sB)f[i+sA]=max(f[i+sA],f[i]+sB);
  25. if(i+bA<=n&&bA<bB)f[i+bA]=max(f[i+bA],f[i]+bB);
  26. }
  27. ll mx=0;
  28. for(int i=0;i<=n;++i)mx=max(mx,f[i]-i);
  29. n+=mx;
  30. memset(f,0,sizeof(f));
  31. for(int i=0;i<=n;++i)
  32. {
  33. if(i+gB<=n&&gA>gB)f[i+gB]=max(f[i+gB],f[i]+gA);
  34. if(i+sB<=n&&sA>sB)f[i+sB]=max(f[i+sB],f[i]+sA);
  35. if(i+bB<=n&&bA>bB)f[i+bB]=max(f[i+bB],f[i]+bA);
  36. }
  37. mx=0;
  38. for(int i=0;i<=n;++i)mx=max(mx,f[i]-i);
  39. printf("%lld\n",mx+n);
  40. return 0;
  41. }

E - Balanced Piles

有若干个数,初始时都是\(0\)。

加上当前的最小值为\(m\),最大值为\(M\),那么就可以随意选择一个值为\(m\)的数,把它变成\([M,M+D]\)中的一个任意整数。

问有多少种方法让所有数都变成\(H\)。

很妙的一道题目。

如果我们要模拟这个过程的话,我们需要的是最大值、最小值。即使知道了,却也没有办法来计算答案,因为我们不知道这些最小值变化之后变成了哪些数。那么如果要模拟就必须知道所有的数。

继续考虑,如果我们知道最小值的个数,假设是\(k\)个,那么如果要改变最小值,一定要恰好\(k\)次操作,此时一共有\(k!\)种操作方案。而变成的最大值是什么、有多少个,显然是可以由我们任意确定的。

那么,假如我们知道了当前的最大值为\(M\),那么显然在操作之后可以任意的把最大值变为\([M,M+D]\)中的任意一个数。同时,我们从初始状态开始,可以任意的控制每次最小值的大小和个数。

那么这就很好办了,我们设\(f[i]\)表示最大值为\(i\)的方案数,它可以转移到\(f[i+1..i+D]\),系数为\(\sum_{i=1}^n i!\),这样子用前缀和就可以做到\(O(n)\)。这样做可行的原因是这些最大值在之后的操作中一定会变成最小值,并且个数也不会产生变化,而这个值的个数又是可以随意确定的,所以方案数恰好就是\(\sum_{i=1}^n i!\)。

所以答案就是\(f[H]\frac{n!}{\sum_{i=1}^ni!}\),至于后面乘的系数,是因为在最小值为\(0\)的时候恰好有\(n\)个,所以方案数是\(n!\)而不是\(\sum_{i=1}^n i!\)。

  1. #include<iostream>
  2. #include<cstdio>
  3. using namespace std;
  4. #define MOD 1000000007
  5. #define MAX 2000200
  6. void add(int &x,int y){x+=y;if(x>=MOD)x-=MOD;}
  7. inline int read()
  8. {
  9. int x=0;bool t=false;char ch=getchar();
  10. while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
  11. if(ch=='-')t=true,ch=getchar();
  12. while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
  13. return t?-x:x;
  14. }
  15. int n,H,D,jc[MAX],f[MAX],s[MAX];
  16. int fpow(int a,int b){int s=1;while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}return s;}
  17. int main()
  18. {
  19. n=read();H=read();D=read();
  20. jc[0]=1;for(int i=1;i<=n;++i)jc[i]=1ll*jc[i-1]*i%MOD;
  21. int sj=0;for(int i=1;i<=n;++i)sj=(sj+jc[i])%MOD;
  22. f[0]=s[0]=1;
  23. for(int i=1;i<=H;++i)f[i]=1ll*sj*(s[i-1]+MOD-(i-D<=0?0:s[i-D-1]))%MOD,s[i]=(s[i-1]+f[i])%MOD;
  24. int ans=1ll*f[H]*jc[n]%MOD*fpow(sj,MOD-2)%MOD;
  25. printf("%d\n",ans);
  26. return 0;
  27. }

F - Diverta City

有一张\(n\)个点的完全图,你需要确定任意两个点之间的边的边权,使得所有的、共\(\frac{n!}{2}\)条哈密顿回路的边权和都不相同。

要求所有边权都是正数,且边权和不超过\(10^{11}\)。

什么神仙构造方法......

考虑增量法,每次加入一个点,定义每个点有一个权值\(f_i\),其中\(f=\{1,2,4,7,12,20,29,38,52,73\}\),这个数列满足任意两个数字都不相同、任意两个数字的和也都不相同。

每次连边的时候就是\(i\rightarrow j(i<j)\),边权为\((M+1)*a_i\),其中\(M\)是加入这个点之前的哈密顿路长度的最大值。

至于这样为啥是对的。。。。

因为每次新的哈密顿回路组成的两条边一定比之前的所有边都要大,所以互相不影响,且又全部不等。。。。

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<algorithm>
  4. using namespace std;
  5. #define ll long long
  6. int n,p[11],a[11]={0,1,2,4,7,12,20,29,38,52,73};
  7. ll g[11][11],M;
  8. int main()
  9. {
  10. scanf("%d",&n);
  11. for(int i=2;i<=n;++i)
  12. {
  13. for(int j=1;j<i;++j)g[i][j]=g[j][i]=(M+1)*a[j];
  14. if(i==n)break;
  15. for(int j=1;j<=i;++j)p[j]=j;
  16. do
  17. {
  18. ll s=0;
  19. for(int j=1;j<i;++j)s+=g[p[j]][p[j+1]];
  20. M=max(M,s);
  21. }while(next_permutation(&p[1],&p[i+1]));
  22. }
  23. for(int i=1;i<=n;++i,puts(""))
  24. for(int j=1;j<=n;++j)
  25. printf("%lld ",g[i][j]);
  26. return 0;
  27. }

AtCoder diverta 2019 Programming Contest 2的更多相关文章

  1. 【AtCoder】diverta 2019 Programming Contest 2

    diverta 2019 Programming Contest 2 A - Ball Distribution 特判一下一个人的,否则是\(N - (K - 1) - 1\) #include &l ...

  2. 【AtCoder】diverta 2019 Programming Contest

    diverta 2019 Programming Contest 因为评测机的缘故--它unrated了.. A - Consecutive Integers #include <bits/st ...

  3. diverta 2019 Programming Contest 2自闭记

    A 签到(a-b problem不用贴了吧,以后atcoder小于300分题均不贴代码) B 发现选择的p,q一定是其中两点间的距离,于是可以O(n2)枚举两点,再O(n2)判断,其实可以做到O(n3 ...

  4. diverta 2019 Programming Contest 2

    A:签到. #include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 ...

  5. diverta 2019 Programming Contest

    A:签到. #include<bits/stdc++.h> using namespace std; #define ll long long #define inf 1000000010 ...

  6. AtCoder SoundHound Inc. Programming Contest 2018 E + Graph (soundhound2018_summer_qual_e)

    原文链接https://www.cnblogs.com/zhouzhendong/p/AtCoder-SoundHound-Inc-Programming-Contest-2018-E.html 题目 ...

  7. 【AtCoder】M-SOLUTIONS Programming Contest

    M-SOLUTIONS Programming Contest A - Sum of Interior Angles #include <bits/stdc++.h> #define fi ...

  8. 【AtCoder】AISing Programming Contest 2019

    本来以为是1199rated的..仔细一看发现是1999,所以就做了一下 这场涨分很轻松啊...为啥又没打 等pkuwc考完我一定打一场atcoder(咕咕咕,咕咕咕,咕咕咕咕咕咕咕~) 但是其实我思 ...

  9. 【AtCoder】Yahoo Programming Contest 2019

    A - Anti-Adjacency K <= (N + 1) / 2 #include <bits/stdc++.h> #define fi first #define se se ...

随机推荐

  1. 互联网渗透测试之Wireshark的高级应用

    互联网渗透测试之Wireshark的高级应用 1.1说明 在本节将介绍Wireshark的一些高级特性 1.2. "Follow TCP Stream" 如果你处理TCP协议,想要 ...

  2. 分母为0的坑(float)

    分母不能为0 对于int 类型,如果分母为0,在程序运行时,会报错. 而对于float 类型,如果分母为0,则不会报错,而是会返回一个infinity(无穷大),也就是NAN. 因为除一个无穷小的数, ...

  3. AVX 指令详解 ,还有SSE指令

    https://blog.csdn.net/fengbingchun/article/details/23598709 本人从来不复制的,自己看!.

  4. os模块补充以及序列化模块

    os模块补充以及序列化模块   一.os模块的补充 1.os.path.abspath 能把存在的相对路径的绝对路径显示出来 path = os.path.abspath("连达day19. ...

  5. 【ORACLE】Oracle提高篇之DECODE

    DECODE含义 decode(条件,值1,返回值1,值2,返回值2,…值n,返回值n,缺省值)这个是decode的表达式,具体的含义解释为: IF 条件=值1 THEN RETURN(翻译值1) E ...

  6. c# 第9节 数据类型之值类型

    本节内容: 1:数据类型是什么 1:数据类型是什么 2:数据类型--值类型 3:值类型和引用类型的区分 画图现象: 3:值类型的种类 整数: 浮点数: 字符:

  7. c# 第七节 编程规范,vs中的各种设置

    本节内容: 1:编程规范 2:vs中的各种设置 3:一个解决方案多个项目的创建.使用 1:编程规范 需要规范的地方: 1: 2: 2:vs中的各种设置 实现: 3:一个解决方案多个项目的创建.使用

  8. 201871010136 -赵艳强《面向对象程序设计(java)》第十六周学习总结

    201871010136-赵艳强<面向对象程序设计(java)>第十六周学习总结   项目 内容 这个作业属于哪个课程 <任课教师博客主页链接>https://www.cnbl ...

  9. python函数中的不定长参数

    python自定义函数中有两中不定长参数,第一种是*name,第二种是**name.加了星号 * 的参数会以元组(tuple)的形式导入,存放所有未命名的变量参数.加了两个星号 ** 的参数会以字典的 ...

  10. Python DataFrame 按条件筛选数据

    原始数据如下. 比如我想查看id等于11396的数据. pdata1[pdata1['id']==11396] 查看时间time小于25320的数据. pdata1[pdata1['time']< ...