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. LightOJ - 1422 (Halloween Costumes)

    题目链接:传送门 题目大意:要参加聚会,对应聚会要穿对应衣服,衣服可以套着穿,也可以脱下来,但脱下来之后不能再穿,问参加完所有聚会至少需要几件衣服? 题目思路:区间DP 一开始自己没有想出来状态转移方 ...

  2. slave_exec_mode参数对主从复制的影响

    主从复制中常会遇到的问题就是1062主键重复.1032 slave上相关记录没找到 如果在读写分离的架构中,slave同步失败会对业务造成很大的影响的(比如主写入了一条数据,从上无法读取到这样对业务影 ...

  3. 并发编程8 线程的创建&验证线程之间数据共享&守护线程&线程进程效率对比&锁(死锁/递归锁)

    1.线程理论以及线程的两种创建方法 2.线程之间是数据共享的与join方法 3.多线程和多进程的效率对比 4.数据共享的补充线程开启太快 5.线程锁 互斥锁 同步锁 6.死锁现象和递归锁 7.守护线程 ...

  4. 解决EF6中表名变成复数的情况

    在用EF6 时,在进行数据调用的时候,总提示数据表名对象错误.. 解决此问题需要在继承DbContext的实体类中 加入: using System; using System.ComponentMo ...

  5. 我的Android进阶之旅------>解决Error:Could not find property 'compile' on org.gradle.api.internal.artifacts.

    1错误描述 解决方法 1错误原因 2解决方法 1.错误描述 刚刚,Android Studio突然编译不了了,报了如下错误: Error:Could not find property 'compil ...

  6. Django-1版本的路由层、Django的视图层和模板层

    一.Django-1版本的路由层(URLconf) URL配置(URLconf)就像Django所支撑网站的目录.它的本质是URL与要为该URL调用的视图函数之间的映射表:我们就是以这种方式告诉Dja ...

  7. Linux下套接字具体解释(九)---poll模式下的IO多路复用server

    參照 poll调用深入解析-从poll的实现来讲poll多路复用模型,非常有深度 poll多路复用 poll的机制与select相似,与select在本质上没有多大差别.管理多个描写叙述符也是进行轮询 ...

  8. 使用 10046 查看执行计划并读懂 trace 文件

    查看 sql 执行计划的方法有许多种, 10046 事件就是其中的一种. 与其他查看 sql 执行计划不同, 当我们遇到比较复杂的 sql 语句, 我们可以通过 10046 跟踪 sql 得到执行计划 ...

  9. appium 中部分 api 的使用方法

    使用的语言是java,appium的版本是1.3.4,java-client的版本是java-client-2.1.0,建议多参考java-client-2.1.0-javadoc. 1.使用Andr ...

  10. 转:asp.net获取url各项参数

    假设当前页完整地址是:http://www.test.com/aaa/bbb.aspx?id=5&name=kelli "http://"是协议名 "www.te ...