传送门

\(A\)

似乎并不难啊然而还是没想出来……

首先我们发现对于一个数\(k\),它能第一个走到当且仅当对于每一个\(i<k\)满足\(x_i\geq 2i-1\),这样我们就可以把所有的\(i\)移到\(2i-1\)然后让\(k\)直接一路过去了。而如果对于每个\(k\)都有这个性质,答案就是\(n!\)

所以从左往右扫,记录当前栈中的元素个数,设当前的\(k\)在栈中的第\(i\)个位置,且\(k\)不满足\(x_k\geq 2i-1\),那么我们必须把前\(i\)个数中移出至少一个才能使剩下的数满足,所以乘上一个系数就好了。最后栈中是可以任意顺序的

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int P=1e9+7;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
const int N=2e5+5;
int x[N],n,res,cnt;
int main(){
scanf("%d",&n),res=1;
fp(i,1,n)scanf("%d",&x[i]);
fp(i,1,n){
if(x[i]<(cnt<<1|1))res=mul(res,cnt+1);
else ++cnt;
}
fp(i,1,cnt)res=mul(res,i);
printf("%d\n",res);
return 0;
}

\(B\)

首先如果整个网格全是白色显然\(gg\)

对于所有不是整列都黑的列,我们肯定得把它们变得整列都黑。而且不难发现,若是没有整行都黑的一行,我们怎么操作都不可能使得一列变黑。所以答案就是使得某一行变黑的最小次数\(+\)不是整列都黑的列数

那么对于一行使其全部变黑的最小次数是多少呢?设这一行为\(i\),其中有\(x\)个白色格子,那么如果第\(i\)列有黑色格子,我们显然可以通过\(x\)次操作使得这一行全部变黑,否则的话就需要\(x+1\)次,多出来的那一次就是为了让第\(i\)列有一个黑色格子

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=505;
char s[N][N];int vis[N],mm[N],n,res,cnt,fl;
int main(){
scanf("%d",&n);
fp(i,1,n)scanf("%s",s[i]+1);
fp(i,1,n)fp(j,1,n)if(s[i][j]=='#')fl=1,vis[j]=1,++mm[j];
if(!fl)return puts("-1"),0;
fp(i,1,n)mm[i]=(mm[i]==n?1:0),cnt+=mm[i];
res=233333;
fp(i,1,n){
R int c=0;
fp(j,1,n)c+=s[i][j]=='.';
cmin(res,n-cnt+c+(vis[i]^1));
}
printf("%d\n",res);
return 0;
}

\(C\)

首先,我们定义\(nxt(i)\)表示最小的\(j\)满足\([i,j)\)操作完之后为空,同理定义\(nxt_{a,b,c...}(i)\)表示最小的\(j\)满足\([i,j)\)操作完之后为\(a,b,c....\)。初始时全都设为\(inf\)

如果\(s[i]=x\),那么显然有\(nxt_x(i)=i+1\),那么其它的该怎么计算呢?

我们发现一次操作的过程相当于维护了一个栈,每一次如果当前元素和栈顶元素相等就把栈顶元素删除或者变成下一个字母。以\(y\)为例,如果\([i,j)\)操作完后是\(y\),那么必然有\([i+1,j)\)操作完之后是\(x\),然后\(s[i]\)和那个剩下的\(x\)一起变成\(y\),即有\(s_y(i)=s_x(s_x(i))\)。同理有\(nxt(i)=nxt_z(nxt_z(i))\)

然而对于那些字典序小于\(x\)的字母呢?显然它们至少得等到\(s[i]\)被消掉,所以有\(nxt_c(i)=nxt_c(nxt(i))\)

从后往前递推,然后倍增维护一下\(nxt(i)\)就好了

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int N=5e5+5;
char s[N];int nxt[N][35],to[N][25],n,q;
int main(){
scanf("%s",s+1),n=strlen(s+1);
fp(i,0,26)nxt[n][i]=nxt[n+1][i]=n+1;
fp(i,0,19)to[n][i]=to[n+1][i]=n+1;
fd(i,n-1,0){
R int c=s[i+1]-'a';
nxt[i][c]=i+1;
fp(j,c+1,26)nxt[i][j]=nxt[nxt[i][j-1]][j-1];
fp(j,0,c-1)nxt[i][j]=nxt[nxt[i][26]][j];
to[i][0]=nxt[i][26];
}
fp(j,1,19)fp(i,0,n-1)to[i][j]=to[to[i][j-1]][j-1];
scanf("%d",&q);
for(int l,r,pos;q;--q){
scanf("%d%d",&l,&r);
pos=--l;
fd(j,19,0)if(to[pos][j]<=r)pos=to[pos][j];
puts(pos==r?"Yes":"No");
}
return 0;
}

\(D\)

好神仙的题……

首先,我们随便选一个点令其\(h(rt)=0\),对于每条边,如果定向为\(u\to v\)则\(h(v)=h(u)+1\),然后\(dfs\)一遍把所有点的\(h\)求出来,那么题中的东西就可以转化成\(d(s,t)={dist(s,t)+h(s)-h(t)\over 2}\)

不难发现题中\(D\)的最大值就是直径除以二上取整,那么代入上式即可得到对于所有点对都需要满足\(|h(s)-h(t)|\leq 2D-dist(s,t)\)

如果直径是偶数,我们取直径的中点\(rt\),那么所有距离直径为\(D\)的点\(h\)应该相同,不妨假设它们全为\(0\),此时可以发现对于树上任意一点\(u\)需要满足\(|h(u)|\leq D-dist(r,u)\)

必要性有了,充分性也可以证明

\[\begin{aligned}
|h(u)-h(v)|\leq |h(u)|+|h(v)|\leq 2D-dist(r,u)-dist(r,v)\leq 2D-dist(u,v)
\end{aligned}
\]

所以只要所有点满足\(|h(u)|\leq D-dist(r,u)\),然后做一个\(dp\)就好了

如果直径是奇数的话,那么中点有两个,分别设为\(s,t\),并令\(s\)子树中那些为白点,\(t\)子树中那些为黑点

那么条件变成

如果\(u\)是白点则\(|h(u)|\leq D-1-dist(s,u)\),如果\(u\)是黑点则\(|h(u)|\leq D-dist(t,u)\)

或者

如果\(u\)是白点则\(|h(u)|\leq D-dist(s,u)\),如果\(u\)是黑点则\(|h(u)|\leq D-1-dist(t,u)\)

因为两种情况里直径的一端必然全部标号为\(0\),而另一端根据直径的奇偶性显然不会为\(0\),所以标号是不会被重复计算的

然而两种情况的确有交集,比方说白点这边所有直径的端点全是\(0\),黑点这边直径的端点全是\(-1\),那么整棵树上所有值\(+1\)之后标号不同但是等价,被我们多数了,需要减掉

交集分别是

如果\(u\)是白点则\(|h(u)|\leq D-1-dist(s,u)\),如果\(u\)是黑点则\(|h(u)+1|\leq D-1-dist(t,u)\)

或者

如果\(u\)是白点则\(|h(u)|\leq D-1-dist(s,u)\),如果\(u\)是黑点则\(|h(u)-1|\leq D-1-dist(t,u)\)

//quming
#include<bits/stdc++.h>
#define R register
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
using namespace std;
const int P=1e9+7;
inline void upd(R int &x,R int y){(x+=y)>=P?x-=P:0;}
inline int add(R int x,R int y){return x+y>=P?x+y-P:x+y;}
inline int dec(R int x,R int y){return x-y<0?x-y+P:x-y;}
inline int mul(R int x,R int y){return 1ll*x*y-1ll*x*y/P*P;}
int ksm(R int x,R int y){
R int res=1;
for(;y;y>>=1,x=mul(x,x))(y&1)?res=mul(res,x):0;
return res;
}
const int N=1005,V=505;
struct eg{int v,nx;}e[N<<1];int head[N],tot;
inline void Add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
int fa[N],dis[N],f[N][N<<1],n,D;
void dfs(int u){go(u)if(v!=fa[u])dis[v]=dis[u]+1,fa[v]=u,dfs(v);}
void get(int u,int lim,int ex){
go(u)if(v!=fa[u])get(v,lim,ex);
R int l=dis[u]-lim+ex,r=lim-dis[u]+ex;
fp(k,l+V,r+V){
f[u][k]=1;
go(u)if(v!=fa[u])f[u][k]=mul(f[u][k],add(f[v][k-1],f[v][k+1]));
}
}
inline int even(R int s){
dis[s]=fa[s]=0,memset(f,0,sizeof(f));
dfs(s),get(s,D,0);
R int res=0;
fp(i,0,V<<1)upd(res,f[s][i]);
return res;
}
inline int odd(R int s,R int t,R int ex){
fa[s]=t,fa[t]=s,dis[s]=dis[t]=0;
memset(f,0,sizeof(f));
dfs(s),dfs(t);
get(s,D+(!ex),0),get(t,D,ex);
R int res=0;
fp(i,1,V<<1)upd(res,mul(f[s][i],add(f[t][i-1],f[t][i+1])));
return res;
}
int main(){
scanf("%d",&n);
for(R int i=1,u,v;i<n;++i)scanf("%d%d",&u,&v),Add(u,v),Add(v,u);
dis[1]=fa[1]=0,dfs(1);
R int rt=1;
fp(i,1,n)if(dis[i]>dis[rt])rt=i;
dis[rt]=fa[rt]=0,dfs(rt);
fp(i,1,n)if(dis[i]>dis[rt])rt=i;
if(dis[rt]&1^1){
D=dis[rt]>>1;
fp(i,1,D)rt=fa[rt];
printf("%d\n",even(rt));
}else{
D=dis[rt]>>1;
fp(i,1,D)rt=fa[rt];
R int s=rt,t=fa[s];
R int res=add(odd(s,t,0),odd(t,s,0));
res=dec(res,add(odd(s,t,1),odd(s,t,-1)));
printf("%d\n",res);
}
return 0;
}

Mujin Programming Challenge 2017题解的更多相关文章

  1. 【AtCoder】Mujin Programming Challenge 2017

    Mujin Programming Challenge 2017 A - Robot Racing 如果每个数都是一个一个间隔开的,那么答案是\(n!\) 考虑把一个数挪到1,第二个数挪到3,以此类推 ...

  2. [SOJ #696]染色(2019-11-10考试)/[Atcoder MUJIN Programming Challenge C]Orange Graph

    题目大意 有一个\(n\)个点\(m\)条边的简单无向连通图,初始为白色,可以执行操作让一些边变黑,要求使得操作后的图不存在黑色的奇环,且不能使得其他的任何变黑而还符合要求.问最后有多少可能结果.\( ...

  3. Mujin Programming Challenge 2017A - Robot Racing【思维题】

    题意: 给你n个人的位置,每个人能往后跳一格或两格到无人的位置,跳到0位置,这个人消失,n个人消失组成一个排列,问有多少种排列. 思路: 额,搞了一整场这个A...代码也巨挫了. 处理成1,3,5,7 ...

  4. Codeforces Gym101522 C.Cheering-字符串 (La Salle-Pui Ching Programming Challenge 培正喇沙編程挑戰賽 2017)

    C.Cheering To boost contestants' performances in the 20th La Salle - Pui Ching Programming Challenge ...

  5. The North American Invitational Programming Contest 2017 题目

    NAIPC 2017 Yin and Yang Stones 75.39% 1000ms 262144K   A mysterious circular arrangement of black st ...

  6. ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. Poor Ramzi -dp+记忆化搜索

    ACM International Collegiate Programming Contest, Tishreen Collegiate Programming Contest (2017)- K. ...

  7. M-SOLUTIONS Programming Contest 2020 题解

    M-SOLUTIONS Programming Contest 2020 题解 目录 M-SOLUTIONS Programming Contest 2020 题解 A - Kyu in AtCode ...

  8. Codeforces Gym101522 D.Distribution of Days-算日期 (La Salle-Pui Ching Programming Challenge 培正喇沙編程挑戰賽 2017)

    D.Distribution of Days The Gregorian calendar is internationally the most widely used civil calendar ...

  9. Codeforces Gym101522 A. Ambiguous Dates (La Salle-Pui Ching Programming Challenge 培正喇沙編程挑戰賽 2017)

    A. Ambiguous Dates There are two popular formats for representing a date: day/month/year or month/da ...

随机推荐

  1. 修改CentOS默认yum源为国内镜像

    参考文档 https://blog.csdn.net/inslow/article/details/54177191 国内主要开源的开源镜像站点应该是网易和阿里云了. 修改为163yum源-mirro ...

  2. text-overflow 全兼容

    text-overflow 全兼容 text-overflow 这个CSS属性用于设置或检索是否使用一个省略标记(...)标示对象内文本的溢出.比起在后台用程序截断文本再附上省略标记的做法,用CSS来 ...

  3. Node.js学习之(第二章:exports和module.exports)

    前言 Node中,每个模块都有一个exports接口对象,我们需要把公共的方法或者字符串挂载在这个接口对象中,其他的模块才可以使用. Node.js中只有模块作用域,默认两个模块之间的变量,方法互不冲 ...

  4. XML 约束

    XML约束 一.约束 约束:规定 xml 文档的书写规则 要求: 1.能够在 xml 中引入约束文档 2.能够简单的读懂约束文档 分类: 1.DTD:一种简单的约束技术(后缀.dtd) 2.Schem ...

  5. 详解iOS的presentViewController(转)

    一.用途和相关概念iOS中显示ViewController的方式有两种push和modal,modal也叫模态,模态显示VC是iOS的重要特性之一,其主要用于有以下场景: - 收集用户输入信息- 临时 ...

  6. Xen虚拟化技术详解---第四章----申请超级调用

    内核驱动程序privcmd负责将位于GuestOS用户空间的超级调用请求传递到GuestOS内核中,与Linux系统的内核驱动程序相同,该操作要在系统调用ioctl()的帮助下完成. 1.关于ioct ...

  7. Python——Str

    在Python内存中,字符串是以unicode形式存储的. str格式,最常用的数据类型格式,分别有 (' ') 引号 ,(" ")双引号,(''' ''')三引号 开头和结尾的引 ...

  8. 使用Junit测试框架学习Java

    前言 在日常的开发中,离不开单元测试,而且在学习Java时,特别是在测试不同API使用时要不停的写main方法,显得很繁琐,所以这里介绍使用Junit学习Java的方法.此外,我使用log4j将结果输 ...

  9. ssh无密码连接

    1. 生成密钥对文件 [root@centos2 ~]# -t 指定加密类型 -b 指定密钥对加密长度 询问1:执行过程中会询问保存位置,一般默认保存在当前用户家目录下的.ssh/目录下 询问2:是否 ...

  10. mount.cifs Windows共享目录权限755问题

    umount -l /usr/local/tomcat7/webapps/dsideal_yy/html/down mount -t cifs -o rw,dir_mode=,file_mode=,s ...