Caddi Programming Contest 2021(AtCoder Beginner Contest 193)

E.Oversleeping

题目描述

给定 (x,y,p,q),求最小的 (t) 满足下面两个等式((k_1,k_2geq 0)):

((p+q)k_1+pleq t<(p+q)k_1+p+q)

((2x+2y)k_2+xleq t<(2x+2y)k_2+x+y)

(1leq x,pleq 10^9,1leq y,qleq 500)

解法

要善于观察数据范围,你看 (y,qleq 500) 就应该知道他们是可以枚举的,我们枚举 (a<y,b<q),因为不等式可以看成若干个区间,所以我们枚举的是和区间左端点的距离,然后用两种方式表示 (t) 可以得到:

[(p+q)k_1+p+a=(2x+2y)k_2+x+b ]

化简一下就可以得到:

[(p+q)k_1-(2x+2y)k_2=b-a+x-p ]

然后就可以用 ( t exgcd) 了,先判断有无解(右边是否被 (gcd) 整除),然后可以求出下面不等式的解:

[(p+q)k_1'+(2x+2y)k_2'=gcd(p+q,2x+2y) ]

然后得到 (k_1=k_1' imesfrac{b-a+x-p}{gcd(p+q,2x+2y)},k_2=-k_2' imesfrac{b-a+x-p}{gcd(p+q,2x+2y)}),但是这两个解不一定合法,我们要把它们都调整成非负数, (k_1,k_2) 可以同时分别加上 (frac{2x+2y}{gcd})(frac{p+q}{gcd}),但是还要调整成最优解,也就是 (k_1) 要是最小的非负整数解,那么模一下即可。

时间复杂度 (O(T imes y imes q imes log x))

#include <cstdio>
#include <iostream>
using namespace std;
#define int __int128
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int T,x,y,p,q,ans;
int gcd(int a,int b)
{
	return !b?a:gcd(b,a%b);
}
int exgcd(int a,int b,int &x,int &y)
{
	if(!b) {x=1;y=0;return a;}
	int d=exgcd(b,a%b,y,x);
	y-=x*(a/b);
	return d;
}
void write(int x)
{
	if(x<=9) {putchar(x+'0');return ;}
	write(x/10);putchar(x%10+'0');
} 
signed main()
{
	T=read();
	while(T--)
	{
		x=read();y=read();p=read();q=read();
		ans=1e36;
		for(int a=0;a<q;a++)
			for(int b=0;b<y;b++)
			{
				int r=b-a+x-p;
				if(r%gcd(p+q,2*x+2*y)) continue;
				int k1=0,k2=0,d=exgcd(p+q,2*x+2*y,k1,k2);
				k1*=r/d;k2=-k2;k2*=r/d;
				int z1=(2*x+2*y)/d,z2=(p+q)/d;
				if(k1<0)
				{
					int t=(-k1+z1-1)/z1;
					k1+=t*z1;k2+=t*z2;
				}
				if(k2<0)
				{
					int t=(-k2+z2-1)/z2;
					k1+=t*z1;k2+=t*z2;
				}
				k1%=z1; 
				ans=min(ans,k1*(p+q)+a+p);
			}
		if(ans==1e36) puts("infinity");
		else write(ans),puts("");
	}
}

F.Zebraness

题目描述

点此看题

解法

出题人水平不够,我们来看一个加强版,这样就可以解决这道题了。

如果每个点选黑选白有代价,同时选黑或同时选白有代价,我们可以建出下面这个图:

那么割掉的是 (1,2,3),或者是 (4,5,6),或者是 (1,2,4,6),或者是 (1,3,4,5),源点理解成染黑,汇点理解成染白,那么也就是如果同时染白会得到 (4) 的贡献,同时染黑会得到 (1) 的贡献。

回归本题,对于钦定的颜色我们需要连 (inf) 的边,对于 ? 则不用连边,由于这道题是一个选黑一个选白有代价,所以说一开始可以对矩阵二分图染色,改一下连的边即可。

#include <cstdio>
#include <queue>
using namespace std;
const int M = 100005;
const int inf = 0x3f3f3f3f;
int read()
{
	int x=0,f=1;char c;
	while((c=getchar())<'0' || c>'9') {if(c=='-') f=-1;}
	while(c>='0' && c<='9') {x=(x<<3)+(x<<1)+(c^48);c=getchar();}
	return x*f;
}
int n,S,T,tot,ans,cnt,f[M],cur[M],dis[M];char s[M];
int dx[2]={1,0},dy[2]={0,1};
struct edge
{
	int v,c,next;
}e[10*M];
void add(int u,int v,int c)
{
	e[++tot]=edge{v,c,f[u]},f[u]=tot;
	e[++tot]=edge{u,0,f[v]},f[v]=tot;
}
int id(int x,int y)
{
	return (x-1)*n+y;
}
int bfs()
{
	for(int i=0;i<=cnt;i++) dis[i]=0;
	queue<int> q;q.push(S);dis[S]=1;
	while(!q.empty())
	{
		int u=q.front();q.pop();
		if(u==T) return 1;
		for(int i=f[u];i;i=e[i].next)
		{
			int v=e[i].v;
			if(e[i].c>0 && !dis[v])
			{
				dis[v]=dis[u]+1;
				q.push(v);
			}
		}
	}
	return 0;
}
int dfs(int u,int ept)
{
	if(u==T) return ept;
	int flow=0,tmp=0;
	for(int &i=cur[u];i;i=e[i].next)
	{
		int v=e[i].v;
		if(e[i].c>0 && dis[v]==dis[u]+1)
		{
			tmp=dfs(v,min(ept,e[i].c));
			if(!tmp) continue;
			e[i].c-=tmp;
			e[i^1].c+=tmp;
			flow+=tmp;
			ept-=tmp;
			if(!ept) break;
		}
	}
	return flow;
}
signed main()
{
	n=read();S=0;cnt=T=n*n+1;tot=1;
	for(int i=1;i<=n;i++)
	{
		scanf("%s",s+1);
		for(int j=1;j<=n;j++)
		{
			if((i+j)&1)
			{
				if(s[j]=='B') add(S,id(i,j),inf);
				if(s[j]=='W') add(id(i,j),T,inf);
			}
			else
			{
				if(s[j]=='W') add(S,id(i,j),inf);
				if(s[j]=='B') add(id(i,j),T,inf);
			}
		}
	}
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
		{
			for(int k=0;k<2;k++)
			{
				int x=i+dx[k],y=j+dy[k];
				if(x<1 || x>n || y<1 || y>n) continue;
				cnt++;
				add(S,cnt,1);
				add(cnt,id(x,y),inf);
				add(cnt,id(i,j),inf);
				cnt++;
				add(id(x,y),cnt,inf);
				add(id(i,j),cnt,inf);
				add(cnt,T,1);
				ans+=2;
			}
		}
	while(bfs())
	{
		for(int i=0;i<=cnt;i++) cur[i]=f[i];
		ans-=dfs(S,inf);
	}
	printf("%d
",ans);
}
原文地址:https://www.cnblogs.com/C202044zxy/p/14806641.html