# AtCoder Grand Contest 038题解

#### A 01Matrix

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int a[1010][1010];
int main(){
int n,m,A,B;
cin>>n>>m>>A>>B;
if(A*2>m||B*2>n)return puts("-1"),0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++){
if(i<=B&&j<=A)putchar('1');
else if(i>B&&j>A)putchar('1');
else putchar('0');
if(j==m)puts("");
}
return 0;
}

#### B Sorting a Segment

#include<bits/stdc++.h>
#define ll long long
using namespace std;
int a[200010],b[2000010],n,m;
int qzl[200010],qzr[200010],hzl[200010],hzr[200010];
int calc(int L,int R){
return a[L]==min(hzl[L],qzl[R])&&a[R]==max(hzr[L],qzr[R]);
}
int main(){
scanf("%d%d",&n,&m);
int tag=-1;
for(int i=0;i<n;i++){
scanf("%d",&a[i]);
if(i>0&&a[i]>a[i-1])b[i]=b[i-1]+1;
else b[i]=1;
if(b[i]>=m)tag++;
}
for(int i=0;i<n;i++){
if(i%m==0)qzl[i]=qzr[i]=a[i];
else qzl[i]=min(qzl[i-1],a[i]),qzr[i]=max(qzr[i-1],a[i]);
}
for(int i=n-1;i>=0;i--){
if(i==n-1||(i+1)%m==0)hzl[i]=hzr[i]=a[i];
else hzl[i]=min(hzl[i+1],a[i]),hzr[i]=max(hzr[i+1],a[i]);
}
int ans=n-m+1;
for(int i=m-1;i<n-1;i++)
if(b[i]<m&&b[i+1]<m&&calc(i-m+1,i+1))ans--;
ans-=max(0,tag);cout<<ans;
return 0;
}

#### C LCMs

\begin{aligned} &\sum_{i=1}^n\sum_{j=i+1}^n\frac{a_ia_j}{\gcd(a_i,a_j)}\\ &=\sum_{d=1}^{max}\frac{1}{d}\sum_{i=1}^n[d|a_i]\sum_{j=i+1}^n[d|a_j]a_ia_j[\gcd(a_i,a_j)=1]\\ &=\sum_{d=1}^{max}\frac{1}{d}\sum_{i=1}^n[d|a_i]\sum_{j=i+1}^n[d|a_j]a_ia_j\sum_{k|a_i,k|a_j}\mu(k)\\ &=\sum_{d=1}^{max}\frac{1}{d}\sum_{i=1}^n[d|a_i]\sum_{j=i+1}^n[d|a_j]a_ia_j\sum_{k|a_i,k|a_j}\mu(k)\\ &=\sum_{d=1}^{max}\frac{1}{d}\sum_{k=1}^{\frac{max}{d}}\mu(k)(\sum_{i=1}^n[dk|a_i]\sum_{j=i+1}^n[dk|a_j]a_ia_j)\\ \end{aligned}

#include<bits/stdc++.h>
#define ll long long
#define p 998244353
#define inv2 499122177
using namespace std;
int mu[1000010],ss[1000010],cnt;bool pri[1000010];
int a[200010],tong[1000010];
int h[1000010],f[1000010];
int n,m,k;
int inv[1000010];
void init(int N){
mu[1]=1;
for(int i=2;i<=N;i++){
if(!pri[i])ss[++cnt]=i,mu[i]=-1;
for(int j=1;i*ss[j]<=N&&j<=cnt;j++){
pri[i*ss[j]]=1;
if(i%ss[j]==0){
mu[i*ss[j]]=0;
break;
}
mu[i*ss[j]]=-mu[i];
}
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]),tong[a[i]]++;
inv[1]=1;
for(int i=2;i<=1000000;i++)inv[i]=1ll*inv[p%i]*(p-p/i)%p;
init(1000000);
for(int i=1;i<=1000000;i++){
for(int j=i;j<=1000000;j+=i)(h[i]+=1ll*tong[j]*j%p)%=p,
(f[i]+=1ll*j*tong[j]%p*j%p)%=p;
}
for(int i=1;i<=1000000;i++)
f[i]=1ll*((1ll*h[i]*h[i]%p-f[i])%p+p)%p*inv2%p;
ll ans=0;
for(int k=1;k<=1000000;k++)
for(int T=k;T<=1000000;T+=k)
(ans+=1ll*inv[k]*mu[T/k]%p*f[T]%p)%=p;cout<<ans;
return 0;
}

#### D Unique Path

#include<bits/stdc++.h>
int n,k,a,b,c,ds,fa[200010],L[200010],R[200010],d;
long long m;
int main(){
scanf("%d%lld%d",&n,&m,&k);ds=n;
for(int i=0;i<n;i++)fa[i]=i;
while(k--){
scanf("%d%d%d",&a,&b,&c);
if(c==0&&p!=q)ds--,fa[q]=p;
if(c==1)L[++d]=a,R[d]=b;
}
puts((m+ds-n>1ll*ds*(ds-1)/2)||(d&&(ds==2||m<n))?"No":"Yes");
return 0;
}

#### E Gachapon

#include<bits/stdc++.h>
#define ll long long
#define p 998244353
using namespace std;
int a[1010],b[1010];
int jc[1010],njc[1010],inv[1010];
vector<int>ret,E[1010],all[1010];
vector<int>mul(vector<int>x,vector<int>y){
vector<int>ret;
int n=x.size(),m=y.size();
ret.resize(n+m-1);
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
(ret[i+j]+=1ll*x[i]*y[j]%p)%=p;return ret;
}
void del(vector<int>&x,vector<int>y){
int n=x.size(),m=y.size();
x.resize(max(n,m));
for(int i=0;i<m;i++)(x[i]-=y[i])%=p;
}
int n=x.size(),m=y.size();
x.resize(max(n,m));
for(int i=0;i<m;i++)(x[i]+=y[i])%=p;
}
int main(){
int n;scanf("%d",&n);
for(int i=0;i<2;i++)jc[i]=njc[i]=inv[i]=1;
for(int i=2;i<=405;i++){
jc[i]=1ll*jc[i-1]*i%p;
inv[i]=1ll*inv[p%i]*(p-p/i)%p;
njc[i]=1ll*njc[i-1]*inv[i]%p;
}
for(int i=0;i<n;i++)scanf("%d %d",&a[i],&b[i]);
int S=0,ans=0;
for(int i=0;i<n;i++)S+=a[i];
for(int i=0;i<n;i++){
for(int k=0,P=1;k<b[i];k++,P=1ll*P*a[i]%p)E[i].push_back(1ll*P*njc[k]%p);
}
for(int i=0;i<n;i++){
for(int k=S-a[i];k>=1;k--)if(all[k].size())
del(all[a[i]+k],mul(E[i],all[k]));
}
for(int i=1;i<=S;i++){
for(int j=0,u=inv[i];j<all[i].size();j++,u=1ll*u*inv[i]%p)
(ans+=1ll*all[i][j]*u%p*jc[j]%p)%=p;
}
(ans+=p)%=p;
cout<<1ll*ans*S%p;
return 0;
}

#### F Two Permutations

• 每个环可以选择动(1)或不动(0)
• 两个环若一起动或一起不动会有一个代价
• 某个环若动或不动会有一个代价
• 要求代价最小值

ISAP好像过不去..?

#include<bits/stdc++.h>
#define ll long long
#define M 400010
using namespace std;
int n,k,cnt,S,T,h,t;
int F[M],L[M],N[M],a[M],c[M],Gap[M],dis[M],q[M],cur[M];
void add(int x,int y,int z,int fla=0){
a[++k]=y;c[k]=z;
N[k]=F[x];F[x]=k;
}
bool BFS(int x,int y){
q[t=1]=x;h=0;
for(int i=1;i<=n;i++)cur[i]=F[i],dis[i]=1000000000;
dis[x]=0;
while(h<t){
x=q[++h];
for(int i=F[x];i;i=N[i])if(c[i]&&dis[a[i]]>n){
dis[a[i]]=dis[x]+1;
if(a[i]==y)return 1;
q[++t]=a[i];
}
}
return dis[y]<=n;
}
int dfs(int x,int T,int flow){
if(x==T)return flow;
int used=0;
for(int i=cur[x];i;i=cur[x]=N[i])if(c[i]&&dis[a[i]]==dis[x]+1){
const int v=dfs(a[i],T,min(flow-used,c[i]));
if(!v)continue;c[i]-=v;c[i^1]+=v;used+=v;
if(used>=flow)return used;
}
return used;
}
int dinic(int S,int T){
int ans=0;
while(BFS(S,T))ans+=dfs(S,T,1000000000);
return ans;
}
int A[200010],B[200010],P[200010],Q[200010],cnt1;
int main(){
scanf("%d",&n);k=1;
for(int i=1;i<=n;i++)scanf("%d",&A[i]),A[i]++;
for(int i=1;i<=n;i++)scanf("%d",&B[i]),B[i]++;
for(int i=1;i<=n;i++)if(!P[i]){
P[i]=++cnt1;
for(int x=A[i];!P[x];x=A[x])P[x]=cnt1;
}
for(int i=1;i<=n;i++)if(!Q[i]){
Q[i]=++cnt1;
for(int x=B[i];!Q[x];x=B[x])Q[x]=cnt1;
}
int all=n;
S=cnt1+1;T=cnt1+2;
for(int i=1;i<=n;i++){
if(A[i]==B[i]){
if(A[i]==i)all--;
}
else {