AtCoder Regular Contest 093


C - Traveling Plan

题意:

给定n个点,求出删去i号点时,按顺序从起点到一号点走到n号点最后回到起点所走的路程是多少。

\(n\le 2e5\)

分析:

可以通过观察发现,无论删去那个点,比全部都走所差距的距离都是\(|a_i-a_{i-1}|-|a_{i+1}-a_i|+|a_{i-1}-a_{i+1}|\)

所以直接枚举即可。

#include <bits/stdc++.h>
using namespace std;
const int MAXN=1e5+7;
int a[MAXN],n,ans;
int main()
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n+1;i++) ans+=abs(a[i]-a[i-1]);
for(int i=1;i<=n;i++){
cout<<ans-abs(a[i]-a[i-1])-abs(a[i]-a[i+1])+abs(a[i-1]-a[i+1])<<endl;
}
}

D - Grid Components

题意:

求一个边长均小于等于100的矩阵,涂成黑白两色,使得白色连通块和黑色连通块的数量分别是A、B。输出这个矩阵的长宽,并输出这个矩阵的具体涂色方案('.'是白色,'#'是黑色)。

\(1\le A,B \le 500\)

分析:

经过观察发现100×100的矩阵一定可以满足所有要求。

那么这么构造,首先把上下两部分平分开,上面是白色下面是黑色,然后一个一个的在白色里填充黑色,黑色同理。

填充方法是从头开始每隔一行一列就填一个,可以证明这样填上下两个矩阵每个矩阵都可以填600个以上所以可以轻松满足要求。

#include <bits/stdc++.h>
using namespace std;
int a,b;
char ch[201][201];
int main()
{
for(int i=1;i<=50;i++)
for(int j=1;j<=100;j++)
ch[i][j]='.';
for(int i=51;i<=100;i++)
for(int j=1;j<=100;j++)
ch[i][j]='#';
cin>>a>>b;
a--;b--;
int cnt1=0,cnt2=0;
for(int i=1;i<=50;i+=2){
if(cnt1==b) break;
for(int j=1;j<=100;j+=2){
if(cnt1==b) break;
cnt1++;
ch[i][j]='#';
}
}
for(int i=52;i<=100;i+=2){
if(cnt2==a) break;
for(int j=1;j<=100;j+=2){
if(cnt2==a) break;
cnt2++;
ch[i][j]='.';
}
}
cout<<"100 100"<<endl;
for(int i=1;i<=100;i++){
for(int j=1;j<=100;j++){
cout<<ch[i][j];
}
cout<<endl;
}
}

E - Bichrome Spanning Tree

题意:

给出一个N个点M条边的无向图,现在要给一些边染黑色或者白色,现在从这些边中选出一些边生成若干棵生成树,要求这些生成树至少包含一条白色的边和一条黑色的边,而且这些生成树的最小值是X,问有多少种染色方法。

分析:

先求一下最小生成树并且设其权值和为s。

那么分情况讨论一下,对于\(s>x\) 的情况,明显答案是0;

对于\(s=x\)的情况,我们可以确定求得那棵树一定是这个最小生成树,所以记录一下所有在最小生成树中的边。那么这些边之外的边就可以随意染色,然后保证最小生成树中的边不是全黑或者全白就可以了。容易得出答案是\(2^{M-m}\times(2^m-1)\)种。

首先必须把S里面的的所有边涂成黑色(或者白色),先假设全部涂成黑色,那么剩余的边,对每一条边单独处理,对边e,它染成白色添加进去之后,如果和集合S中的边形成的满足题意的最小生成树权重w′小于X,那么这条边只能继续涂成黑色;如果w′大于X,它涂成黑色白色都无所谓;然后把w′等于X的边的数量统计下来,假设有tot条边,可以知道这tot条边只要有一条边是白色就行了,因为只要选中这里面的一条边,剩余的边肯定都是从集合S中选出来了, 不可能再从其它边中选取,如果必须涂成黑色的有d条边, 那么答案就是2M−tot−d∗(2tot−1),最终结果再乘以2就行了,就是必须涂成一种颜色的有两种涂法

(借鉴自:AtCoder Regular Contest 093(E-Bichrome Spanning Tree)

#include <bits/stdc++.h>
using namespace std;
const int MAXN=2010;
#define ll long long
#define int ll
const int mo=1e9+7;
struct po
{
int x,y,l;
}a[MAXN];
bool cmp(po a,po b){return a.l<b.l;}
int n,m,tmp,x;
int f[MAXN];
int find(int x) {return x==f[x]?x:f[x]=find(f[x]);}
int kruskal(int now)
{
int res=0;
for(int i=1;i<=n;i++) f[i]=i;
if(now) {res+=a[now].l;f[a[now].x]=a[now].y;}
for(int i=1;i<=m;i++){
int r1=find(a[i].x),r2=find(a[i].y);
if(r1==r2) continue;
res+=a[i].l;
f[r1]=r2;
}
return res;
}
inline int power(int x,int k)
{
int cnt=1;
while(k){
if(k&1) cnt=cnt*x%mo;
k>>=1;
x=x*x%mo;
}
return cnt;
}
int val,cnt1,cnt2;
int ans;
main()
{
cin>>n>>m>>x;
for(int i=1;i<=m;i++) cin>>a[i].x>>a[i].y>>a[i].l;
sort(a+1,a+m+1,cmp);
tmp=kruskal(0);
if(tmp>x){
cout<<0;
return 0;
}
if(tmp==x){
for(int i=1;i<=m;i++){
val=kruskal(i);
if(val==x) cnt1++;
else cnt2++;
}
ans=((power(2,cnt1)-2)*power(2,cnt2)%mo+mo)%mo;
} else {
for(int i=1;i<=m;i++){
val=kruskal(i);
if(val==x) cnt1++;
else if(val>x) cnt2++;
}
ans=(2*(power(2,cnt1)-1)%mo*power(2,cnt2)%mo+mo)%mo;
}
cout<<ans;
}

F - Dark Horse

题意:

有2N个选手参与一场比赛,比赛规则是:相邻的两个人比赛一次,败者淘汰掉,胜者继续进行,直到只剩一个人为止。现在给出1号选手会败给哪些选手并且已知其他选手之间均满足:两个选手比赛,编号小的一定会胜利。现在可以安排每个选手初始的位置,要钦定1号选手最后获胜,求能满足条件的初始位置的方案数。

分析:

由于可以明显发现1号无论站在哪里最后的胜负方案数都是一样的,所以可以直接就让1号在一号位置,然后将答案最后乘上\(2^n\)即可。

考虑1号一定会打n场,而且每次都会和\(2^n+1...2^{n+1}\)中编号最小的人打,所以保证其中没有人在ad这个集合内就可以了。

以下部分摘自dalao:

接下来就是本题最有趣的地方了:容斥原理。

设S为N个块的一个子集,\(f(S)\)表示这个子集中所有块的最小值均在A的范围内(其余块是否在A的范围内不考虑)的方案数。

这样一来,最终答案即为\(∑(−1)^{|S|}f(S)\)

将A从大到小排序,依次考虑加入\(A_i\)后的\(f(S)\)。

1、成为一个块的最小值:那么在这个块中,必须填充相应数量的,编号比AiAi大的选手,组合数统计。

2、不成为块的最小值,不操作即可\((dp[i][S]+=dp[i−1][S])\)。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define int ll
const int MAXN=20;
const int MAXM=2<<16+1;
const int mo=1e9+7;
int n,m,a[MAXN],bit[MAXN],c[MAXM];
int fac[MAXM],inv[MAXM],dp[MAXN][MAXM];
int power(int x,int k)
{
int cnt=1;
while(k){
if(k&1) cnt=cnt*x%mo;
x=x*x%mo;
k>>=1;
}
return cnt;
}
int C(int x,int y){return 1ll*fac[x]*inv[y]%mo*inv[x-y]%mo;}
main()
{
cin>>n>>m;
for(int i=1;i<=m;i++) cin>>a[i];
reverse(a+1,a+m+1);
for(int i=0;i<=n-1;i++) bit[i]=1<<i;
int cnt=1<<n;fac[0]=1;
for(int i=1;i<=cnt;i++)
fac[i]=1ll*fac[i-1]*i%mo;
inv[cnt]=power(fac[cnt],mo-2);
for(int i=cnt-1;i>=0;i--)
inv[i]=inv[i+1]*(i+1ll)%mo;
int u=(1<<n)-1;dp[0][0]=1;
for(int i=1;i<=m;i++)
for(int s=0;s<=u;s++){
int l=cnt-a[i]+1-s;
dp[i][s]=(dp[i][s]+dp[i-1][s])%mo;
for(int j=0;j<=n-1;j++){
if(l<bit[j]) break;
if(bit[j]&s) continue;
dp[i][s^bit[j]]=(dp[i][s^bit[j]]+(1ll*dp[i-1][s]*C(l-1,bit[j]-1))%mo*fac[bit[j]]%mo)%mo;
}
}
int ans=fac[cnt-1]; c[0]=1;
for(int s=1;s<=u;s++){
c[s]=-c[s-(s&-s)];
ans=(ans+1ll*c[s]*dp[m][s]*fac[cnt-1-s]%mo)%mo;
}
ans=(1ll*ans*cnt%mo+mo)%mo;
cout<<ans;
}

AtCoder Regular Contest 093的更多相关文章

  1. Atcoder Regular Contest 093 D - Dark Horse(组合数学+状压 dp)

    Atcoder 题面传送门 & 洛谷题面传送门 常规题,简单写写罢((( 首先 \(1\) 的位置是什么不重要,我们不妨钦定 \(1\) 号选手最初就处在 \(1\) 号位置,最后答案乘个 \ ...

  2. AtCoder Regular Contest 093 E: Bichrome Spanning Tree(生成树)

    Bichrome Spanning Tree 题意: 给出一个n个点,m条边的无向连通图,现在要给每条边染色,可以染成黑色或者白色. 现在要求在染色完毕后,找出一个至少包含一条黑边和一条白边的最小生成 ...

  3. AtCoder Regular Contest 061

    AtCoder Regular Contest 061 C.Many Formulas 题意 给长度不超过\(10\)且由\(0\)到\(9\)数字组成的串S. 可以在两数字间放\(+\)号. 求所有 ...

  4. AtCoder Regular Contest 094 (ARC094) CDE题解

    原文链接http://www.cnblogs.com/zhouzhendong/p/8735114.html $AtCoder\ Regular\ Contest\ 094(ARC094)\ CDE$ ...

  5. AtCoder Regular Contest 092

    AtCoder Regular Contest 092 C - 2D Plane 2N Points 题意: 二维平面上给了\(2N\)个点,其中\(N\)个是\(A\)类点,\(N\)个是\(B\) ...

  6. AtCoder Regular Contest 094

    AtCoder Regular Contest 094 C - Same Integers 题意: 给定\(a,b,c\)三个数,可以进行两个操作:1.把一个数+2:2.把任意两个数+1.求最少需要几 ...

  7. AtCoder Regular Contest 095

    AtCoder Regular Contest 095 C - Many Medians 题意: 给出n个数,求出去掉第i个数之后所有数的中位数,保证n是偶数. \(n\le 200000\) 分析: ...

  8. AtCoder Regular Contest 102

    AtCoder Regular Contest 102 C - Triangular Relationship 题意: 给出n,k求有多少个不大于n的三元组,使其中两两数字的和都是k的倍数,数字可以重 ...

  9. AtCoder Regular Contest 096

    AtCoder Regular Contest 096 C - Many Medians 题意: 有A,B两种匹萨和三种购买方案,买一个A,买一个B,买半个A和半个B,花费分别为a,b,c. 求买X个 ...

随机推荐

  1. 【BZOJ2836】魔法树 树链剖分

    [BZOJ2836]魔法树 Description Input Output Sample Input 4 0 1 1 2 2 3 4 Add 1 3 1 Query 0 Query 1 Query ...

  2. [HackerRank] The Longest Common Subsequence

    This is the classic LCS problem. Since it requires you to print one longest common subsequence, just ...

  3. 机械迷城MAC下载及攻略

    点击下载 无意间在verycd上看到这个游戏,很好玩的一个游戏. 画风非常可爱,有点复古风. 这里是 机械迷城 的专题频道 http://pc.pcgames.com.cn/pczq/jxmc/

  4. delphi xe学习随意记录

    学习来源(根据他们的资料整理) 论坛:http://www.coder163.com(有视频) 博客:http://del.cnblogs.com/(万一的博客) 1.1.1    命名规范的概述 1 ...

  5. 2.sublime的配置,

    sublime配置完成后,感觉好强大..

  6. Advanced Bash-Scripting Guide(学习笔记)

    http://www.tldp.org/LDP/abs/html/index.html       11.1. Loops tp://www.tldp.org/LDP/abs/html/loops1. ...

  7. MySQL日期时间字段

    mysql支持的日期时间类型有:DATETIME. TIMESTAMP.DATE.TIME.YEAR. 几种类型比较如下: DATETIME DATETIME 用于表示 年月日 时分秒,是 DATE和 ...

  8. Linux内核协议栈相关资料链接

    1.Linux内核网络分析(个人博客集合,分析较清晰) http://blog.csdn.net/qy532846454/article/category/1385933/2

  9. 吴超老师课程--Sqoop的安装和介绍

    SQOOP是用于对数据进行导入导出的.    (1)把MySQL.Oracle等数据库中的数据导入到HDFS.Hive.HBase中    (2)把HDFS.Hive.HBase中的数据导出到MySQ ...

  10. python并发编程之IO模型(Day38)

    一.IO模型介绍 为了更好的学习IO模型,可以先看同步,异步,阻塞,非阻塞 http://www.cnblogs.com/linhaifeng/articles/7430066.html#_label ...