AtCoder Beginner Contest 193 部分题解
E - Oversleeping
求是否存在\(t\)满足\(t=t_1(mod (2X+2Y)) and t=t_2(mod (P+Q))\)
注意到\(Q\)和\(Y\)非常小,直接枚举套个\(exCRT\)就行了(虽然赛场上没看出来,\(exCRT\)也忘了记得快速乘
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#include<cmath>
#define inf 9223372036854775807
#define LL long long
using namespace std;
template <class I>
inline void read(I &z)
{
z=0;
char c=getchar();int base=1;
while (!isdigit(c) && c!='-') c=getchar();
if (c=='-') c=getchar(),base=-1;
while (isdigit(c)) z=z*10+c-'0',c=getchar();
z*=base;
}
LL mul(LL x,LL y,LL p)
{
LL z=0;
for (;y;y>>=1,x=(x<<1)%p) if (y&1) z=(z+x)%p;
return z;
}
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(!b) return x=1,y=0,a;
LL d=exgcd(b,a%b,x,y),t=x;
return x=y,y=t-a/b*y,d;
}
LL excrt(LL n,LL a[],LL b[])//x=a[i] (mod b[i])
{
LL x,y;
LL B=b[1],A=a[1];//x=A (mod B)
for (int i=2;i<=n;++i)
{
LL d=exgcd(B,b[i],x,y),t=b[i]/d;
LL c=((a[i]-A)%b[i]+b[i])%b[i];//Bx=c (mod b[i])
if (c%d) return -1;
x=mul(x,c/d,t);//t=>最小正正整数解
A+=B*x,B=B*t;
A=(A%B+B)%B;
}
return A;
}
LL ans,x,y,p,q,a[3],b[3];
int main(int argc, char const *argv[])
{
LL T;
read(T);
while (T--)
{
read(x),read(y),read(p),read(q);
ans=inf;
b[1]=x*2+y*2,b[2]=p+q;
for (LL k1=x;k1<x+y;++k1)
for (LL k2=p;k2<p+q;++k2)
{
a[1]=k1,a[2]=k2;
LL tmp=excrt(2,a,b);
if (tmp==-1) continue; else ans=min(ans,tmp);
}
if (ans==inf) printf("infinity\n"); else printf("%lld\n",ans);
}
return 0;
}
F - Zebraness
一个棋盘每格有\(B\)和\(W\)两种颜色以及\(?\),相邻的两个不同会有\(1\)的贡献,要求最大化贡献。
一眼最小鸽集合划分模型,和文理分科差不多又差好多。而且忘了怎么建模了。棋盘黑白染色后把白色全都翻转,就和朴素的集合划分模型一样了。相邻的两格连一条流量为\(1\)的边,\(S\)向\(B\),\(W\)向\(T\)连\(inf\),跑最小鸽然后拿贡献和减掉最小鸽。
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<cstring>
using namespace std;
template <class I>
inline void read(I &z)
{
z=0;
char c=getchar();int base=1;
while (!isdigit(c) && c!='-') c=getchar();
if (c=='-') c=getchar(),base=-1;
while (isdigit(c)) z=z*10+c-'0',c=getchar();
z*=base;
}
const int N=105,M=50010,inf=2147483647;
struct E { int c,to,next; };
E e[100010];
int point=1,v[N*N],h[N*N],gap[N*N],s,t,n;
char a[N][N];
int f(int x,int y) { return (x-1)*n+y; }
inline void add(int x,int y,int c)
{
e[++point]=(E){c,y,v[x]},v[x]=point;
e[++point]=(E){0,x,v[y]},v[y]=point;
}
int dfs(int cur,int f)
{
if (cur==t || !f) return f;
int ans=0,flow;
for (int i=v[cur];i;i=e[i].next)
{
int u=e[i].to;
if (!e[i].c) continue;
if (h[u]==h[cur]-1 && (flow=dfs(u,min(e[i].c,f))))
{
e[i].c-=flow,e[i^1].c+=flow;
f-=flow,ans+=flow;
if (!f) break;
}
}
if (!ans) if (!--gap[h[cur]]) h[s]=n*n+3; else ++gap[++h[cur]];
return ans;
}
int Max_Flow()
{
int ans=0;
while (h[s]<=n*n+2)
ans+=dfs(s,inf);
return ans;
}
int main(int argc, char const *argv[])
{
read(n),t=(s=n*n+1)+1;
for (int i=1;i<=n;++i) scanf("%s",a[i]+1);
for (int i=1;i<=n;++i)
for (int j=1;j<=n;++j)
{
if (a[i][j]=='?') continue;
if ((i+j+1)&1)
{
if (a[i][j]=='B') add(s,f(i,j),inf);
if (a[i][j]=='W') add(f(i,j),t,inf);
}
else
{
if (a[i][j]=='W') add(s,f(i,j),inf);
if (a[i][j]=='B') add(f(i,j),t,inf);
}
}
for (int i=1;i<n;++i)
for (int j=1;j<=n;++j)
add(f(i,j),f(i+1,j),1),add(f(i+1,j),f(i,j),1);
for (int i=1;i<=n;++i)
for (int j=1;j<n;++j)
add(f(i,j),f(i,j+1),1),add(f(i,j+1),f(i,j),1);
printf("%d",2*n*(n-1)-Max_Flow());
return 0;
}

浙公网安备 33010602011771号