AtCoder Regular Contest 115(without F)

ARC115 A - Two Choices

题目传送门


分析

可以发现正确答案数量相同当且仅当 \(S_i\) xor \(S_j\) 所含有的 1 的数量为偶数。

再将这个简化一下,正确答案相同当且仅当 \(S_i\)\(S_j\) 所含有的 1 的数量同奇偶。


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
int n,cnt[2];
signed main(){
	scanf("%d%*d",&n);
	for (rr int i=1;i<=n;++i){
		rr char c=getchar(); rr int now=0;
		while (!isdigit(c)) c=getchar();
		while (isdigit(c)) now+=(c&1),c=getchar();
		++cnt[now&1];
	}
	return !printf("%lld\n",1ll*cnt[0]*cnt[1]);
}

ARC115 B - Plus Matrix

题目传送门


分析

可以发现第 \(i\) 行可以由第 \(1\) 行 加减一个数得到,由此判无解,然后再选出最小的一行作为 \(B\) 即可


代码

#include <cstdio>
#include <cctype>
#define rr register
using namespace std;
int n,a[511][511],b[511][511],mn;
inline signed iut(){
	rr int ans=0,f=1; rr char c=getchar();
	while (!isdigit(c)) f=(c=='-')?-f:f,c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans*f;
}
signed main(){
	scanf("%d",&n),mn=1;
	for (rr int i=1;i<=n;++i){
	    for (rr int j=1;j<=n;++j) a[i][j]=iut();
        for (rr int j=1;j<n;++j) b[i][j]=a[i][j+1]-a[i][j];
	}
	for (rr int i=1;i<n;++i)
	for (rr int j1=1;j1<n;++j1)
	for (rr int j2=j1+1;j2<=n;++j2)
	    if (b[j1][i]!=b[j2][i]) return !puts("No");
	for (rr int i=2;i<=n;++i)
	    if (a[mn][1]>a[i][1]) mn=i;
	puts("Yes");
	for (rr int i=1;i<=n;++i) printf("%d%c",a[i][1]-a[mn][1],i==n?10:32);
	for (rr int i=1;i<=n;++i) printf("%d%c",a[mn][i],i==n?10:32);
	return 0;
}

ARC115 C - ℕ Coloring

题目传送门


分析

如果第一个位置填1,可以发现限制条件实际就是深度要超过约数的深度,直接建图跑最长路即可


代码

#include <cstdio>
#define rr register
using namespace std;
const int N=100011;
struct node{int y,next;}e[N<<4];
int a[N],as[N],n,et;
inline void print(int ans){
    if (ans>9) print(ans/10);
    putchar(ans%10+48);
}
inline void add(int x,int y){
	e[++et]=(node){y,as[x]},as[x]=et;
}
signed main(){
	scanf("%d",&n),a[1]=1;
	for (rr int i=1;i<=n;++i)
	    for (rr int j=i*2;j<=n;j+=i) add(j,i);
	for (rr int i=2;i<=n;++i)
	for (rr int j=as[i];j;j=e[j].next)
	    if (a[i]<a[e[j].y]+1) a[i]=a[e[j].y]+1;
	for (rr int i=1;i<=n;++i) print(a[i]),putchar(i==n?10:32);
	return 0;
}

ARC115 D - Odd Degree

题目传送门


分析

如果将 \(k\) 个奇点连向一个虚点,那么题目就转化成求欧拉回路的问题,

由于每条非树边都独立出来,所以 \(n\) 个点,\(m\) 条边的合法生成子图为 \(2^{m-n+1}\)

然后连通块选择点作为奇点直接dp就可以了


代码

#include <cstdio>
#include <cctype>
using namespace std;
const int N=5011,mod=998244353;
struct node{int y,next;}e[N<<1];
int two[N],c[N][N],as[N],v[N],et=1,n,m,dp[N],sub,edge;
int iut(){
	int ans=0; char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=ans*10+c-48,c=getchar();
	return ans;
}
void print(int ans){
	if (ans>9) print(ans/10);
	putchar(ans%10+48);
}
int mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
void dfs(int x){
	if (v[x]) return; v[x]=1,++sub;
	for (int i=as[x];i;i=e[i].next)
	    dfs(e[i].y),++edge;
}
int main(){
	n=iut(),m=iut(),c[0][0]=two[0]=dp[0]=1;
	for (int i=1;i<=m;++i) two[i]=mo(two[i-1],two[i-1]);
	for (int i=1;i<=m;++i){
		int x=iut(),y=iut();
		e[++et]=(node){y,as[x]},as[x]=et;
		e[++et]=(node){x,as[y]},as[y]=et; 
	}
	for (int i=1;i<=n;++i){
		c[i][0]=c[i][i]=1;
		for (int j=1;j<i;++j)
		    c[i][j]=mo(c[i-1][j-1],c[i-1][j]);
	}
	for (int i=1;i<=n;++i)
	if (!v[i]){
		sub=edge=0,dfs(i),edge>>=1;
		for (int j=n;~j;--j){
			if (j&1) continue;
			dp[j]=1ll*dp[j]*two[edge-sub+1]%mod;
			for (int k=2;k<=j;k+=2){
				if (k>sub) break;
				dp[j]=mo(dp[j],1ll*dp[j-k]*c[sub][k]%mod*two[edge-sub+1]%mod);
			}
		}
	}
	for (int i=0;i<=n;++i) print(dp[i]),putchar(10);
	return 0;
} 

ARC115 E - LEQ and NEQ

题目传送门


分析

考虑容斥。

\[\large dp[i]=\sum dp[j]\min_{k=j}^i\{a_k\}*(-1)^{i-j-1} \]

直接用单调栈预处理,然后奇数位置插入 \(dp\) 值的相反数即可


代码

#include <cstdio>
#include <cctype>
#include <cstring>
#define rr register
using namespace std;
const int mod=998244353,N=500011; typedef long long lll;
int ww[N<<2],wc[N<<2],lazy[N<<2],stac[N],a[N],n,las[N],Top,dp[N];
inline signed iut(){
	rr int ans=0; rr char c=getchar();
	while (!isdigit(c)) c=getchar();
	while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();
	return ans;
}
inline signed mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
inline void upd(int k,int l,int r,int x,int y){
	if (l==r) {ww[k]=wc[k]=y; return;}
	if (lazy[k]){
		wc[k<<1]=(lll)ww[k<<1]*lazy[k]%mod,
		wc[k<<1|1]=(lll)ww[k<<1|1]*lazy[k]%mod,
		lazy[k<<1]=lazy[k<<1|1]=lazy[k];
	}
	rr int mid=(l+r)>>1;
	if (x<=mid) upd(k<<1,l,mid,x,y);
	    else upd(k<<1|1,mid+1,r,x,y);
	ww[k]=mo(ww[k<<1],ww[k<<1|1]);
	wc[k]=mo(wc[k<<1],wc[k<<1|1]);
}
inline void update(int k,int l,int r,int x,int y,int z){
	if (l==x&&r==y) {wc[k]=(lll)ww[k]*z%mod,lazy[k]=z; return;}
	rr int mid=(l+r)>>1;
	if (lazy[k]){
		wc[k<<1]=(lll)ww[k<<1]*lazy[k]%mod,
		wc[k<<1|1]=(lll)ww[k<<1|1]*lazy[k]%mod,
		lazy[k<<1]=lazy[k<<1|1]=lazy[k];
	}
	if (y<=mid) update(k<<1,l,mid,x,y,z);
	else if (x>mid) update(k<<1|1,mid+1,r,x,y,z);
	    else update(k<<1,l,mid,x,mid,z),update(k<<1|1,mid+1,r,mid+1,y,z);
	wc[k]=mo(wc[k<<1],wc[k<<1|1]);
	ww[k]=mo(ww[k<<1],ww[k<<1|1]); 
}
signed main(){
	n=iut()+1,a[1]=-1e9,
	dp[1]=stac[Top=1]=1;
	for (rr int i=2;i<=n;++i){
		a[i]=iut();
		while (Top&&a[stac[Top]]>=a[i]) --Top;
		las[i]=stac[Top],stac[++Top]=i;
	}
	for (rr int i=2;i<=n;++i){
		upd(1,1,n,i-1,(i&1)?dp[i-1]:(mod-dp[i-1]));
		if (las[i]<i) update(1,1,n,las[i],i-1,a[i]);
		dp[i]=(i&1)?wc[1]:(mod-wc[1]);
	}
	return !printf("%d",dp[n]);
}
posted @ 2021-11-11 07:21  lemondinosaur  阅读(107)  评论(0)    收藏  举报