传送门

这场表现的宛如一个\(zz\)

\(A\)

先直接把前\(b\)行全写成\(1\),再把前\(a\)列取反就行

const int N=1005;
char mp[N][N];int n,m,a,b;
int main(){
scanf("%d%d%d%d",&n,&m,&a,&b);
fp(i,1,b)fp(j,1,m)mp[i][j]=1;
fp(i,1,n)fp(j,1,a)mp[i][j]^=1;
fp(i,1,n){
fp(j,1,m)putchar(mp[i][j]+'0');
putchar('\n');
}
return 0;
}

\(B\)

先除去区间内本就有序的情况,那么操作\([i,i+k-1]\)和\([i+1,i+k]\)等价当且仅当\(p_i\)是\([i,i+k-1]\)中最小的元素且\(p_{i+k}\)是\([i+1,i+k]\)中最大的元素,那么就不计算\(i+1\)就行了。用单调栈就能判断

//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=2e5+5;
int a[N],st[N],up[N],dw[N],dr[N],top,n,res,k,fl;
int main(){
scanf("%d%d",&n,&k);
fp(i,1,n)scanf("%d",&a[i]);
st[top=0]=0;
fp(i,1,n){
while(top&&a[i]>a[st[top]])--top;
up[i]=(st[top]<=i-k),st[++top]=i;
}
st[top=0]=n+1;
fd(i,n,1){
while(top&&a[i]<a[st[top]])--top;
dw[i]=(st[top]>=i+k),st[++top]=i;
}
for(R int l=1,r=2;r<=n;l=r++){
while(r<=n&&a[r]>a[r-1])++r;
fp(i,l+k-1,r-1)dr[i]=1;
}
fp(i,k,n)if(dr[i])fl=1;
else if(!(up[i]&&dw[i-k]))++res;
printf("%d\n",res+fl);
return 0;
}

\(C\)

方便起见设

\[\begin{aligned}
Ans
&=\sum_{i=1}^n\sum_{j=1}^n \text{lcm}(a_i,a_j)
\end{aligned}
\]

最后的答案减一减就行了

然后开始颓柿子

\[\begin{aligned}
Ans
&=\sum_{i=1}^n\sum_{j=1}^n \text{lcm}(a_i,a_j)\\
&=\sum_{d=1}^n d\sum_{i=1}^n\sum_{j=1}^n [d|a_i][d|a_j]{a_i\over d}{a_j\over d}[\gcd({a_i\over d},{a_j\over d})=1]\\
&=\sum_{d=1}^n d\sum_{i=1}^n\sum_{j=1}^n [d|a_i][d|a_j]{a_i\over d}{a_j\over d}\sum_{t|{a_i\over d},t|{a_j\over d}}\mu(t)\\
&=\sum_{T=1}^n \sum_{d|T}d\sum_{i=1}^n\sum_{j=1}^n [T|a_i][T|a_j]{a_i\over T}{a_j\over T}\times{T^2\over d^2}\mu({T\over d})\\
&=\sum_{T=1}^n \sum_{i=1}^n\sum_{j=1}^n [T|a_i][T|a_j]{a_i\over T}{a_j\over T}T\sum_{d|T}{T\over d}\mu({T\over d})\\
&=\sum_{T=1}^n \sum_{i=1}^n\sum_{j=1}^n [T|a_i][T|a_j]{a_i\over T}{a_j\over T}T\sum_{d|T}d\mu(d)\\
\end{aligned}
\]

先\(O(n\log n)\)预处理\(s(T)=\sum_{d|T}d\mu(d)\),然后记\(cnt[k]\)表示\(a_i=k\)的个数,\(O(n\log n)\)计算即可

//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=998244353;
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=1e6+5,L=1e6;
bitset<N>vis;int p[N],mu[N],cnt[N],a[N],st[N],c[N],s[N],top,n,m,res;
void init(int n=L){
mu[1]=1;
fp(i,2,n){
if(!vis[i])p[++m]=i,mu[i]=-1;
for(R int j=1;j<=m&&i*p[j]<=n;++j){
vis[i*p[j]]=1;
if(i%p[j]==0)break;
mu[i*p[j]]=-mu[i];
}
}
fp(i,1,n)upd(mu[i],P);
fp(i,1,n)for(R int j=i;j<=n;j+=i)upd(s[j],mul(i,mu[i]));
}
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d",&n);
init();
fp(i,1,n)scanf("%d",&a[i]),++cnt[a[i]];
fp(T,1,L){
R int sum=0;
for(R int j=T;j<=L;j+=T)upd(sum,mul(j/T,cnt[j]));
sum=mul(sum,sum),sum=mul(sum,mul(T,s[T]));
upd(res,sum);
}
fp(i,1,n)res=dec(res,a[i]);
res=mul(res,(P+1)>>1);
printf("%d\n",res);
return 0;
}

\(D\)

先把\(m=n-1\)的情况特判掉,接下来只考虑\(m\geq n\)

建一张新图\(G\),对于所有\(C_i=0\)的关系\((a,b)\)看成\(a,b\)在同一个连通块里,这样缩完点之后对于每一个\(C_i=1\)的关系\((a,b)\)必须满足\(a,b\)在不同连通块里否则无解

记连通块个数为\(k\),如果我们从每个连通块中取出一个点,把所有给出的点连成一个环,每个连通块内随便连一棵生成树,这样总的边数为\(n\),且能保证任意两个处于不同连通块中的点之间至少\(2\)条路径,这就是边数的下界,且因为之前我们保证了\(m\geq n\)所以下界必然能达到

再来考虑上界,每个连通块内连生成树,选出的点之间连完全图,边数就是\(n-k+{k (k-1)\over 2}=n+{k(k-3)\over 2}\),那么上界肯定是越大越好,也就是说我们不需要再加额外的边,直接用\(G\)中的边才能保证\(k\)最大

\(ps:\)对于总的连通块个数为\(1\)或\(2\)的边界情况都会在判上界的时候处理掉所以没必要讨论

所以只要\(m\leq n+{k(k-3)\over 2}\)就有解,否则无解

//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;
typedef long long ll;
const int N=1e5+5;
struct eg{int u,v,c;}e[N];
ll m,sum;int fa[N],n,q;
inline int find(R int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
int main(){
scanf("%d%lld%d",&n,&m,&q);
fp(i,1,n)fa[i]=i;
for(R int i=1,u,v;i<=q;++i){
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].c);
++e[i].u,++e[i].v;
if(!e[i].c)u=find(e[i].u),v=find(e[i].v),fa[u]=v;
if(e[i].c&&m==n-1)return puts("No"),0;
}
if(m==n-1)return puts("Yes"),0;
for(R int i=1,u,v;i<=q;++i)if(e[i].c){
u=find(e[i].u),v=find(e[i].v);
if(u==v)return puts("No"),0;
}
fp(i,1,n)sum+=(find(i)==i);
sum=n-sum+(1ll*sum*(sum-1)>>1);
puts(m<=sum?"Yes":"No");
return 0;
}

\(E\)

首先,通过\(Min-Max\)容斥转化一下,问题变成对于一个集合\(S\),设\(S={t_1,t_2,..,t_m}\),其中第一个\(t_i\)出现次数到达\(b_{t_i}\)时的期望步数

我们设一个状态\(x_1,x_2,..,x_m(x_i<b_{t_i})\),表示\(t_i\)恰好出现了\(x_i\)次,设\(P\)表示生成的数在集合\(S\)中的概率,那么这个状态发生变化的期望步数就是\({1\over P}\),同时如果能算出这个状态出现的概率\(p\),那么它对答案的贡献就是\({p\over P}\)了。如果对所有合法的\(x\)都能计算出贡献,加起来就是集合\(S\)中第一个\(t_i\)出现次数到达\(b_{t_i}\)时的期望步数了

对于\(p\),设\(X=\sum_{i=1}^m t_i\),则有

\[\begin{aligned}
p=X!\prod_{i=1}^m\left({t_i\over P}\right)^{x_i}{1\over x_i!}
\end{aligned}
\]

那么就可以算了,设\(f[i][j][k]\)表示考虑到第\(i\)个数,其中选的集合中\(X=j\),\(\sum a=k\)的总的贡献,最后对于每一个合法的状态加上贡献即可

//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=998244353;
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=405;
int fac[N],ifac[N],bin[N],f[N][N][N],a[N],b[N],n,s1,s2;
inline void init(R int n=400){
fac[0]=ifac[0]=1;fp(i,1,n)fac[i]=mul(fac[i-1],i);
ifac[n]=ksm(fac[n],P-2);fd(i,n-1,1)ifac[i]=mul(ifac[i+1],i+1);
}
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d",&n);
init();
fp(i,1,n)scanf("%d%d",&a[i],&b[i]);
f[0][0][0]=P-1;
fp(i,1,n){
fp(j,0,s1)fp(k,0,s2)f[i][j][k]=f[i-1][j][k];
bin[0]=1;fp(j,1,b[i]-1)bin[j]=mul(bin[j-1],a[i]);
fp(j,0,b[i]-1)bin[j]=mul(bin[j],ifac[j]);
fp(j,0,s1)fp(k,0,s2)fp(v,0,b[i]-1)
upd(f[i][j+v][k+a[i]],P-mul(f[i-1][j][k],bin[v]));
s1+=b[i]-1,s2+=a[i];
}
R int res=0;
fp(i,0,s1)fp(j,1,s2){
R int ret=mul(f[n][i][j],fac[i]);
ret=mul(ret,ksm(j,P-1-i));
upd(res,mul(ret,mul(s2,ksm(j,P-2))));
}
printf("%d\n",res);
return 0;
}

\(F\)

首先,我们从\(i\)向\(p_i\)连边,那么肯定是形成了若干个环,且环上所有数只能同时选\(i\)或者\(p_i\),我们记同时选\(i\)为\(1\),同时选\(p_i\)为\(0\)

同理从\(i\)向\(q_i\)连边,不过记同时选\(i\)为\(0\),同时选\(q_i\)为\(1\)

然后记\(x[i]\)和\(y[i]\)分别表示\(i\)处于哪个环,那么\(i\)是否有贡献是跟它所在的两个环的取值以及\(p_i\)和\(q_i\)的值有关的,根据\(p_i\)和\(q_i\)的取值讨论一下就行了

懒得写讨论了直接贴题解(其中\(v_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)
#define gg(u) for(int &i=cur[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,M=1e6+5,inf=0x3f3f3f3f;
inline int min(R int x,R int y){return x<y?x:y;}
struct eg{int v,nx,w;}e[M];int head[N],tot=1;
inline void add(R int u,R int v,R int w){
e[++tot]={v,head[u],w},head[u]=tot;
e[++tot]={u,head[v],0},head[v]=tot;
}
int dep[N],cur[N],S,T,n;
bool bfs(){
memset(dep,-1,(T+1)<<2);
memcpy(cur,head,(T+1)<<2);
static int q[N];
int h=1,t=0,u;q[++t]=S,dep[S]=0;
while(h<=t){
u=q[h++];
go(u)if(e[i].w&&dep[v]<0)q[++t]=v,dep[v]=dep[u]+1;
}
return ~dep[T];
}
int dfs(int u,int lim){
if(u==T||!lim)return lim;
int fl=0,f;
gg(u)if(dep[v]==dep[u]+1&&(f=dfs(v,min(lim,e[i].w)))){
fl+=f,lim-=f,e[i].w-=f,e[i^1].w+=f;
if(!lim)break;
}
if(!fl)dep[u]=-1;
return fl;
}
inline int dinic(){R int res=0;while(bfs())res+=dfs(S,inf);return res;}
int p[N],q[N],blp[N],blq[N],s0[N],s1[N],sum,cnt;
int main(){
// freopen("testdata.in","r",stdin);
scanf("%d",&n);
fp(i,1,n)scanf("%d",&p[i]),++p[i];
fp(i,1,n)scanf("%d",&q[i]),++q[i];
fp(i,1,n)if(!blp[i]){
++cnt;
for(R int j=i;!blp[j];j=p[j])blp[j]=cnt;
}
fp(i,1,n)if(!blq[i]){
++cnt;
for(R int j=i;!blq[j];j=q[j])blq[j]=cnt;
}
S=0,T=cnt+1;
fp(i,1,n)sum+=p[i]!=q[i];
fp(i,1,n){
if(p[i]==q[i]){
if(p[i]==i)continue;sum+=2;
add(S,blp[i],1),add(blq[i],T,1),add(blp[i],blq[i],2);
}else{
if(p[i]==i)add(S,blq[i],1);
else if(q[i]==i)add(blp[i],T,1);
else add(blp[i],blq[i],1);
}
}
printf("%d\n",sum-dinic());
return 0;
}

AtCoder Grand Contest 038 题解的更多相关文章

  1. AtCoder Grand Contest 038题解

    好久没更了 写点东西吧= = A 01Matrix 简单构造 左上角和右下角染成1其他染成0即可 #include<bits/stdc++.h> #define ll long long ...

  2. AtCoder Grand Contest 038 简要题解

    从这里开始 比赛目录 Problem A 01 Matrix Code #include <bits/stdc++.h> using namespace std; typedef bool ...

  3. AtCoder Grand Contest 017 题解

    A - Biscuits 题目: 给出 \(n\) 个物品,每个物品有一个权值. 问有多少种选取方式使得物品权值之和 \(\bmod\space 2\) 为 \(p\). \(n \leq 50\) ...

  4. Atcoder Grand Contest 038 F - Two Permutations(集合划分模型+最小割)

    洛谷题面传送门 & Atcoder 题面传送门 好久前做的题了--今天偶然想起来要补个题解 首先考虑排列 \(A_i\) 要么等于 \(i\),要么等于 \(P_i\) 这个条件有什么用.我们 ...

  5. Atcoder Grand Contest 054 题解

    那天晚上由于毕业晚会与同学吃饭喝酒没打 AGC,第二天稍微补了下题,目前补到了 E,显然 AGC 的 F 对于我来说都是不可做题就没补了(bushi A 简单题,不难发现如果我们通过三次及以上的操作将 ...

  6. AtCoder Grand Contest 030题解

    第一次套刷AtCoder 体验良好 传送门 Poisonous Cookies cout<<b+min(c,a+b+); Tree Burning 难度跨度有点大啊 可以证明当第一次转向之 ...

  7. AtCoder Grand Contest 031题解

    题面 传送门 题解 比赛的之后做完\(AB\)就开始发呆了--简直菜的一笔啊-- \(A - Colorful\ Subsequence\) 如果第\(i\)个字母选,那么它前面任意一个别的字母的选择 ...

  8. AtCoder Grand Contest 039 题解

    传送门 \(A\) 首先只有一串的情况下,遇到相同的肯定是改后面那一个最优,然后两串的话可能要分奇偶讨论一下 //quming #include<bits/stdc++.h> #defin ...

  9. AtCoder Grand Contest 017题解

    传送门 \(A\) 直接转移就是了 typedef long long ll; const int N=55; ll f[N][2];int a[N],n,p; int main(){ scanf(& ...

随机推荐

  1. Spark 系列(一)—— Spark简介

    一.简介 Spark 于 2009 年诞生于加州大学伯克利分校 AMPLab,2013 年被捐赠给 Apache 软件基金会,2014 年 2 月成为 Apache 的顶级项目.相对于 MapRedu ...

  2. ApachShiro 一个系统 两套验证方法-(后台管理员登录、前台App用户登录)同一接口实现、源码分析

    需求: 在公司新的系统里面博主我使用的是ApachShiro 作为安全框架.作为后端的鉴权以及登录.分配权限等操作 管理员的信息都是存储在管理员表 前台App 用户也需要校验用户名和密码进行登录.但是 ...

  3. 论文笔记 Large Pose 3D Face Reconstruction from a Single Image via Direct Volumetric CNN Regression

    Large Pose 3D Face Reconstruction from a Single Image via Direct Volumetric CNN Regression 该文献采用一个新型 ...

  4. SpringBoot--整合Mybatis+druid

    分为两部分,首先替换默认数据源为阿里德鲁伊并添加监控,其次是SpringBoot下使用Mybatis 替换数据源为德鲁伊 首先在配置文件里配置好数据库连接的基本信息,如username passwor ...

  5. python --- 字符编码学习小结(二)

    距离上一篇的python --- 字符编码学习小结(一)已经过去2年了,2年的时间里,确实也遇到了各种各样的字符编码问题,也能解决,但是每次都是把所有的方法都试一遍,然后终于正常.这种方法显然是不科学 ...

  6. 使用jQuery开发dialog对话框插件

    1.插件使用 首先引入 jquery 库,然后引入 dialog.js.dialog.css,如下: <script type="text/javascript" src=& ...

  7. top 命令 详解

    VIRT:virtual memory usage 虚拟内存 1.进程“需要的”虚拟内存大小,包括进程使用的库.代码.数据等 2.假如进程申请100m的内存,但实际只使用了10m,那么它会增长100m ...

  8. OO第4次博客作业

    OO第4次博客作业 一.第4单元设计 第四单元主要围绕UML图的结构进行JAVA代码编写,对JAVA的层次结构进行更多的认识.个人认为编程操作在实质上与上一章的PathContainer有许多的相同之 ...

  9. 1+X证书学习日志——定位

    ## 静态定位:                 position:static;    默认值,指定left/right/top/bottom/  没有作用.                 pos ...

  10. Mac 修改hostname

    mac终端上输入命令: sudo scutil --set HostName newname # 实例 sudo scutil --set HostName master