AtCoder Grand Contest 005题解
\(A\)
咕咕
const int N=5e5+5;
char s[N];int res,n,sum;
int main(){
scanf("%s",s+1),res=n=strlen(s+1);
fp(i,1,n)if(s[i]=='S')++sum;
else if(sum)--sum,res-=2;
printf("%d\n",res);
return 0;
}
\(B\)
咕咕
//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 cmin(T&a,const T&b){return a>b?a=b,1:0;}
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
typedef long long ll;
const int N=2e5+5,inf=0x3f3f3f3f;
int a[N],l[N],r[N],st[N],n,top;ll res;
int main(){
scanf("%d",&n);
fp(i,1,n)scanf("%d",&a[i]);
a[0]=a[n+1]=0,st[++top]=0;
fp(i,1,n){
while(top&&a[i]<a[st[top]])--top;
l[i]=st[top],st[++top]=i;
}
st[top=1]=n+1;
fd(i,n,1){
while(top&&a[i]<a[st[top]])--top;
r[i]=st[top],st[++top]=i;
}
fp(i,1,n)res+=1ll*a[i]*(i-l[i])*(r[i]-i);
printf("%lld\n",res);
return 0;
}
\(C\)
因为树上所有直径有同一个中点或同一条中边,那么\(dis\)最小的点只能有\(1\)个或者两个
然后我们从中点开始构造一条直径,如果无法构造出无解,否则剩下的点都可以挂在直径上而满足条件
最后判一下构造出的直径是否满足它给出的\(dis\)即可
const int N=105;
int c[N],n,mn=233,mx;
int main(){
scanf("%d",&n);
for(R int i=1,x;i<=n;++i)scanf("%d",&x),++c[x],cmin(mn,x),cmax(mx,x);
if(c[mn]>2)return puts("Impossible"),0;
fp(i,mn+1,mx)if(c[i]<2)return puts("Impossible"),0;
if(c[mn]==2&&mn!=mx-mn+1)return puts("Impossible"),0;
if(c[mn]==1&&mn!=mx-mn)return puts("Impossible"),0;
return puts("Possible"),0;
}
\(D\)
这种题目显然是容斥了
然而如果直接枚举有几个点选了不该选的数会有问题,因为有的点选不该选的数有两种方案,有的点选了别的点就不能选
发现选了之后\(i\)只会影响\(...,i-4k,i-2k,i+2k,i+4k,...\)的数的选法,那么我们把所有模\(2k\)意义下相等的位置一起考虑,记\(f_{i,j,0/1/2}\)表示考虑到这一类中的第\(i\)个数,选了其中\(j\)个,第\(i\)个数不选\(/\)选择在这个位置放\(i-k/\)选择在这个位置放\(i+k\)的方案数,转移即可,最后暴力加到全局的背包里,即可计算出\(s[i]\)表示至少有这\(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 cmin(T&a,const T&b){return a>b?a=b,1:0;}
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
const int P=924844033;
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=2005;
int n,k,res,len,f[N][3],g[N][3],s[N],t[N],fac[N];
void calc(R int x){
memset(f,0,sizeof(f));
f[0][0]=1;
R int p=0;
for(;x<=n;x+=(k<<1)){
fp(i,0,p){
g[i][0]=f[i][0],g[i][1]=f[i][1],g[i][2]=f[i][2];
f[i][0]=f[i][1]=f[i][2]=0;
}
fp(i,0,p){
R int s=add(g[i][0],add(g[i][1],g[i][2]));
upd(f[i][0],s);
if(x>k)upd(f[i+1][1],dec(s,g[i][2]));
if(x+k<=n)upd(f[i+1][2],s);
}
++p;
}
memset(t,0,sizeof(t));
fp(i,0,len)fp(j,0,p)upd(t[i+j],mul(s[i],add(f[j][0],add(f[j][1],f[j][2]))));
len+=p;
fp(i,0,len)s[i]=t[i];
}
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d%d",&n,&k);
fac[0]=1;fp(i,1,n)fac[i]=mul(fac[i-1],i);
s[0]=1;
fp(i,1,min(k<<1,n))calc(i);
fp(i,0,len)upd(res,i&1?dec(0,mul(fac[n-i],s[i])):mul(fac[n-i],s[i]));
printf("%d\n",res);
return 0;
}
\(E\)
博弈论菜鸡在此
首先如果存在一个情况,\(A\)在\(u\),\(B\)在\(v\),如果\(u\)能走到的任何一条边在蓝树上到\(v\)的距离都小于等于\(1\),\(A\)只能等死了,否则如果存在一条边\((u,v)\)满足蓝树上的距离大于\(2\),那么\(A\)就可以一直利用这条边绕\(B\)了,此时输出\(-1\)
如果会被追到,那么以蓝树上的\(Y\)为根,我们发现\(A\)根本走不出这棵子树,那么我们找到所有\(A\)能到达的点,然后到其中深度最大的点等死就行了
//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(head,u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmin(T&a,const T&b){return a>b?a=b,1:0;}
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
const int N=1e6+5;
struct eg{int v,nx;}e[N<<1];int bl[N],rd[N],tot;
inline void add(R int *head,R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
int fr[N],to[N],dep[N],fa[N],dfn[N],low[N],ok[N],vis[N],dis[N],tim,n,S,T;
void dfs(int *head,int u){
dfn[u]=++tim;
go(head,u)if(v!=fa[u])fa[v]=u,dep[v]=dep[u]+1,dfs(head,v);
low[u]=tim;
}
inline bool ck(R int u,R int v){
if(dfn[u]>dfn[v])swap(u,v);if(low[u]>=low[v])return dep[v]-dep[u]>2;
if(fa[u]==fa[v])return false;return true;
}
int q[N];
void bfs(){
int h=1,t=0,u;q[++t]=S,vis[S]=1;
while(h<=t){
u=q[h++];
go(rd,u)if(!vis[v]){
dis[v]=dis[u]+1;
if(dis[v]<dep[v])vis[v]=1,q[++t]=v;
}
}
}
int main(){
scanf("%d%d%d",&n,&S,&T);
for(R int i=1,u,v;i<n;++i)scanf("%d%d",&u,&v),fr[i]=u,to[i]=v;
for(R int i=1,u,v;i<n;++i)scanf("%d%d",&u,&v),add(bl,u,v),add(bl,v,u);
dfs(bl,T);
for(R int i=1,u,v;i<n;++i){
u=fr[i],v=to[i];
if(ck(u,v))ok[u]=ok[v]=1;
else add(rd,u,v),add(rd,v,u);
}
bfs();
fp(i,1,n)if(vis[i]&&ok[i])return puts("-1"),0;
R int res=0;
fp(i,1,n)if(vis[i])cmax(res,dep[i]<<1);
printf("%d\n",res);
return 0;
}
\(F\)
先考虑如何计算单个\(k\),那么对于每个点分别计算贡献,一个点会被计入贡献的次数是\({n\choose k}-\sum_{v\in son_u}{sz_v\choose k}\),其中\(sz_v\)表示以\(u\)为根时\(v\)子树的大小
那么\(n\)个点加起来就是\(n\times {n\choose k}-\sum_{i=1}^n cnt[i]\times {i\choose k}\),把组合数拆成阶乘的形式就可以把后面看成一个卷积了,\(NTT\)即可
//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=924844033,gi=554906420;
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=(1<<19)+5;
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 fac[N],ifac[N],r[25][N],rt[2][N],f[N],g[N],inv[25];
int n,lim,d;
inline void swap(R int &x,R int &y){R int t=x;x=y,y=t;}
inline int C(R int n,R int m){return m>n?0:1ll*fac[n]*ifac[m]%P*ifac[n-m]%P;}
void init(){
fac[0]=ifac[0]=1;fp(i,1,262144)fac[i]=mul(fac[i-1],i);
ifac[262144]=ksm(fac[262144],P-2);fd(i,262143,1)ifac[i]=mul(ifac[i+1],i+1);
fp(d,1,19){
fp(i,1,(1<<d)-1)r[d][i]=(r[d][i>>1]>>1)|((i&1)<<(d-1));
inv[d]=ksm(1<<d,P-2);
}
for(R int t=(P-1)>>1,i=1,x,y;i<=262144;i<<=1,t>>=1){
x=ksm(5,t),y=ksm(gi,t),rt[0][i]=rt[1][i]=1;
fp(k,1,i-1)
rt[1][i+k]=mul(rt[1][i+k-1],x),
rt[0][i+k]=mul(rt[0][i+k-1],y);
}
}
void NTT(int *A,int ty){
fp(i,0,lim-1)if(i<r[d][i])swap(A[i],A[r[d][i]]);
R int t;
for(R int mid=1;mid<lim;mid<<=1)
for(R int j=0;j<lim;j+=(mid<<1))
fp(k,0,mid-1)
A[j+k+mid]=dec(A[j+k],t=mul(rt[ty][mid+k],A[j+k+mid])),
A[j+k]=add(A[j+k],t);
if(!ty){
t=inv[d];
fp(i,0,lim-1)A[i]=mul(A[i],t);
}
}
int sz[N];
void dfs(int u,int fa){
sz[u]=1;
go(u)if(v!=fa){
dfs(v,u),sz[u]+=sz[v];
++f[n-sz[v]],++f[sz[v]];
}
}
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d",&n);
for(R int i=1,u,v;i<n;++i)scanf("%d%d",&u,&v),Add(u,v),Add(v,u);
dfs(1,0);init();
lim=1,d=0;
while(lim<=(n<<1))lim<<=1,++d;
fp(i,0,n)f[i]=mul(f[i],fac[i]),g[i]=ifac[n-i];
NTT(f,1),NTT(g,1);
fp(i,0,lim-1)f[i]=mul(f[i],g[i]);
NTT(f,0);
fp(i,1,n)printf("%d\n",dec(mul(n,C(n,i)),mul(f[i+n],ifac[i])));
return 0;
}
AtCoder Grand Contest 005题解的更多相关文章
- AtCoder Grand Contest 005
AtCoder Grand Contest 005 A - STring 翻译 给定一个只包含\(ST\)的字符串,如果出现了连续的\(ST\),就把他删去,然后所有位置前移.问最后剩下的串长. 题解 ...
- AtCoder Grand Contest 017 题解
A - Biscuits 题目: 给出 \(n\) 个物品,每个物品有一个权值. 问有多少种选取方式使得物品权值之和 \(\bmod\space 2\) 为 \(p\). \(n \leq 50\) ...
- AtCoder Grand Contest 005 C - Tree Restoring
题目传送门:https://agc005.contest.atcoder.jp/tasks/agc005_c 题目大意: 给定一个长度为\(N\)的整数序列\(A_i\),问能否构造一个\(N\)个节 ...
- Atcoder Grand Contest 005 E - Sugigma: The Showdown(思维题)
洛谷题面传送门 & Atcoder 题面传送门 记先手移动棋子的树为红树,后手移动棋子的树为蓝树. 首先考虑一个性质,就是如果与当前红色棋子所在的点相连的边中存在一条边,满足这条边的两个端点在 ...
- Atcoder Grand Contest 054 题解
那天晚上由于毕业晚会与同学吃饭喝酒没打 AGC,第二天稍微补了下题,目前补到了 E,显然 AGC 的 F 对于我来说都是不可做题就没补了(bushi A 简单题,不难发现如果我们通过三次及以上的操作将 ...
- AtCoder Grand Contest 030题解
第一次套刷AtCoder 体验良好 传送门 Poisonous Cookies cout<<b+min(c,a+b+); Tree Burning 难度跨度有点大啊 可以证明当第一次转向之 ...
- AtCoder Grand Contest 031题解
题面 传送门 题解 比赛的之后做完\(AB\)就开始发呆了--简直菜的一笔啊-- \(A - Colorful\ Subsequence\) 如果第\(i\)个字母选,那么它前面任意一个别的字母的选择 ...
- AtCoder Grand Contest 005【A栈模拟,B单调栈】
挖草,AtCoder实在是太吊了~ %%%,目前只A了两题: A题: 就是利用栈模拟一下就好了:S进栈,T的话有S就出栈,然后len减一下就好了: #include <bits/stdc++.h ...
- AtCoder Grand Contest 039 题解
传送门 \(A\) 首先只有一串的情况下,遇到相同的肯定是改后面那一个最优,然后两串的话可能要分奇偶讨论一下 //quming #include<bits/stdc++.h> #defin ...
随机推荐
- java之struts2之类型转换
在使用servlet开发中,表单中提交的数据到servlet后都是字符串类型,需要程序员手动进行类型转换. 但是到struts2后,基本数据类型struts2都可以转换.但是如果是自定义类型,stru ...
- java后台获取微信小程序openid
一.jar包准备 1.在网盘下载 链接:https://pan.baidu.com/s/15HAAWOg_yn768g4s9IrcPg 提取码:hgj0 二.在pom文件中添加依赖 1.将外部的引入的 ...
- BUAAOO-Third-Summary
目录 从DBC到JML SMT solver 使用 JML toolchain的可视化输出 和我的测试结果 规格的完善策略 架构设计 debug情况 心得体会 一.从DBC到JML 契约式设计(Des ...
- kubernetes第八章--NFS PersistentVolume
- spark源码阅读--SparkContext启动过程
##SparkContext启动过程 基于spark 2.1.0 scala 2.11.8 spark源码的体系结构实在是很庞大,从使用spark-submit脚本提交任务,到向yarn申请容器,启 ...
- iOS - Target-Action机制创建自己的UI控件需要了解的知识
我们在开发应用的时候,经常会用到各种各样的控件,诸如按钮(UIButton).滑块(UISlider).分页控件(UIPageControl)等.这些控件用来与用户进行交互,响应用户的操作.我们查看这 ...
- 机器码-字节码-CLR-JIT-托管代码-非托管代码-unsafe-GC-fixed
0. 机器码 直接由机器码对应平台的CPU执行的指令集, 因此无法在其他指令集的CPU上运行. 无法跨平台. 由本地代码编译得到. (托管代码通过JIT生成) 1. 字节码 即 bytecode 是一 ...
- 【转载】Javascript使用Math.random()随机数函数生成1至1000的随机数
在Javascript代码编写过程中,有时候我们需要使用Js来生成随机数,清除ajax的get请求缓存的时候我们会带上一个随机数来解决此问题,此外在其他应用中也可能使用到随机数,在Javascript ...
- js原型,原型链
先铺垫下原型规则: 1.所有的引用类型(数组,对象,函数)都具有对象特性,可自由扩展属性(出了null外) 2.所有的引用类型(数组,对象,函数)都有一个__proto__属性(隐式原型),属性值是一 ...
- mysql审计插件-记录所有sql语句
https://www.58jb.com/html/160.html https://www.jianshu.com/p/a0e0aec3cb6f MySQL审计工具Audit Plugin安装使用 ...