AtCoder diverta 2019 Programming Contest 2

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

然后就写写题解QWQ。

A - Ball Distribution

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

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

现在重新一看题解。。。

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

#include<iostream>
#include<cstdio>
using namespace std;
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int main()
{
int n=read(),k=read();
if(k==1)puts("0");
else printf("%d\n",n-k);
return 0;
}

B - Picking Up

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

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

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

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

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<set>
using namespace std;
#define MAX 55
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n;
struct Node{int x,y;}p[MAX];
bool operator<(Node a,Node b){if(a.x!=b.x)return a.x<b.x;return a.y<b.y;}
set<Node> M;
int ans=1e9;
int main()
{
n=read();
for(int i=1;i<=n;++i)p[i].x=read(),p[i].y=read();
if(n==1){puts("1");return 0;}
sort(&p[1],&p[n+1]);
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j)
{
int P=p[j].x-p[i].x,Q=p[j].y-p[i].y;
if(P<0)P=-P,Q=-Q;
M.clear();int ret=0;
for(int k=1;k<=n;++k)
{
if(!M.count((Node){p[k].x-P,p[k].y-Q}))++ret;
M.insert(p[k]);
}
ans=min(ans,ret);
}
printf("%d\n",ans);
return 0;
}

C - Successive Subtraction

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

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

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

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

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

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

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define ll long long
#define MAX 100100
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,a[MAX],b[MAX],s;
vector<pair<int,int> > T;
int main()
{
n=read();
for(int i=1;i<=n;++i)a[i]=read();
sort(&a[1],&a[n+1]);
for(int i=2;i<n;++i)b[i]=a[i]<0;
b[1]=1;b[n]=0;
for(int i=2;i<n;++i)
if(b[i])T.push_back(make_pair(a[n],a[i])),a[n]-=a[i];
else T.push_back(make_pair(a[1],a[i])),a[1]-=a[i];
T.push_back(make_pair(a[n],a[1]));
printf("%d\n",a[n]-a[1]);
for(auto a:T)printf("%d %d\n",a.first,a.second);
return 0;
}

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\)一次就做完了。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define ll long long
#define MAX 25000100
inline ll read()
{
ll x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
ll f[MAX],n,gA,sA,bA,gB,sB,bB;
int main()
{
n=read();
gA=read();sA=read();bA=read();
gB=read();sB=read();bB=read();
for(int i=0;i<=n;++i)
{
if(i+gA<=n&&gA<gB)f[i+gA]=max(f[i+gA],f[i]+gB);
if(i+sA<=n&&sA<sB)f[i+sA]=max(f[i+sA],f[i]+sB);
if(i+bA<=n&&bA<bB)f[i+bA]=max(f[i+bA],f[i]+bB);
}
ll mx=0;
for(int i=0;i<=n;++i)mx=max(mx,f[i]-i);
n+=mx;
memset(f,0,sizeof(f));
for(int i=0;i<=n;++i)
{
if(i+gB<=n&&gA>gB)f[i+gB]=max(f[i+gB],f[i]+gA);
if(i+sB<=n&&sA>sB)f[i+sB]=max(f[i+sB],f[i]+sA);
if(i+bB<=n&&bA>bB)f[i+bB]=max(f[i+bB],f[i]+bA);
}
mx=0;
for(int i=0;i<=n;++i)mx=max(mx,f[i]-i);
printf("%lld\n",mx+n);
return 0;
}

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!\)。

#include<iostream>
#include<cstdio>
using namespace std;
#define MOD 1000000007
#define MAX 2000200
void add(int &x,int y){x+=y;if(x>=MOD)x-=MOD;}
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int n,H,D,jc[MAX],f[MAX],s[MAX];
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;}
int main()
{
n=read();H=read();D=read();
jc[0]=1;for(int i=1;i<=n;++i)jc[i]=1ll*jc[i-1]*i%MOD;
int sj=0;for(int i=1;i<=n;++i)sj=(sj+jc[i])%MOD;
f[0]=s[0]=1;
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;
int ans=1ll*f[H]*jc[n]%MOD*fpow(sj,MOD-2)%MOD;
printf("%d\n",ans);
return 0;
}

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\)是加入这个点之前的哈密顿路长度的最大值。

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

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

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define ll long long
int n,p[11],a[11]={0,1,2,4,7,12,20,29,38,52,73};
ll g[11][11],M;
int main()
{
scanf("%d",&n);
for(int i=2;i<=n;++i)
{
for(int j=1;j<i;++j)g[i][j]=g[j][i]=(M+1)*a[j];
if(i==n)break;
for(int j=1;j<=i;++j)p[j]=j;
do
{
ll s=0;
for(int j=1;j<i;++j)s+=g[p[j]][p[j+1]];
M=max(M,s);
}while(next_permutation(&p[1],&p[i+1]));
}
for(int i=1;i<=n;++i,puts(""))
for(int j=1;j<=n;++j)
printf("%lld ",g[i][j]);
return 0;
}

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. wpf 工程生成dll

    在WPF项目里,当工程里包含窗体时候, 不可以使用类库的方式生产dll,虽然系统支持引用exe 文件,但总是觉得不如dll习惯,后来发现,新建个项目,类型选择“WPF自定义类件库”,名称和工程名称相同 ...

  2. HBuilder 云打包生成 .apk 文件所需的安卓证书如何获取以及文件打包前必须的设置

    在 HBuilder 云打包功能中,生在 .apk 文件虽然平台提供了免费的 安卓证书,但如果有其它需求,比如想发布,那么就需要自己去申请各种类型的证书了,这里介绍几个工具,方便在线生成证书并配置到打 ...

  3. influxdb-1.7.8(centos 7) 部署

    1.官方下载: https://dl.influxdata.com/influxdb/releases/influxdb-1.7.8.x86_64.rpm 2.安装软件 sudo yum locali ...

  4. windows下git安装过程

    参考廖雪峰博客: https://www.liaoxuefeng.com/wiki/896043488029600/896067074338496 git网站下载程序:   https://git-s ...

  5. 安装教程-VMware 12 安装企业级 CentOS 7.6

    企业级 CentOS 7.6 系统的安装 1.实验描述 在虚拟机中,手动安装 CentOS 7.6 操作系统,为学习 Linux 提供平台,因此,有的参数有些差异,请勿较真. 2.实验环境 物理机系统 ...

  6. Docker容器服务(三)

    一.创建容器 容器是Docker的另一个核心概念. 简单地说,容器是镜像的一个运行实例,所不同的是,它带有额外的可写文件层. 1.1创建一个容器 使用docker create命令创建的容器处于停止状 ...

  7. 逆向破解之160个CrackMe —— 010-011

    CrackMe —— 010 160 CrackMe 是比较适合新手学习逆向破解的CrackMe的一个集合一共160个待逆向破解的程序 CrackMe:它们都是一些公开给别人尝试破解的小程序,制作 c ...

  8. src和href 如何做好seo 前端页面有那三层 AMD和CMD 规范的区别 渐进增强

    1==>简述一下src与href的区别 src用于替换当前元素: href用于在当前文档和引用资源之间确立联系 2==>.谈谈以前端角度出发做好SEO需要考虑什么? a. 了解搜索引擎如何 ...

  9. mysql基础sql进阶

    回顾前面的基础命令语句 修改数据表 添加字段: alter table 表名 add 字段名 列类型[not null|null][primary key][unique][auto_incremen ...

  10. grep命令用法

    linux中grep命令的用法 作为linux中最为常用的三大文本(awk,sed,grep)处理工具之一,掌握好其用法是很有必要的. 首先谈一下grep命令的常用格式为:grep  [选项]  ”模 ...