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;
}
posted @ 2021-03-06 01:20  Harexx  阅读(94)  评论(0)    收藏  举报