zoukankan      html  css  js  c++  java
  • 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);
    }
    
  • 相关阅读:
    hibernate对应关系详解(转)
    mybatis genertor两种使用方式(文件+项目)
    YII2 union 不同数据结构时 解决方案
    Yii2 分表后 使用 union all 分页实现代码
    Beyond Compare 4.2.10手动破解
    Xshell 6+Xftp 6官方下载免费版
    Navicat Premium
    yii2的Console定时任务创建
    内嵌多个youtube视频并展现该频道所有视频列表
    video.js 动态获取URL 并播放youtube视频
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/14806641.html
Copyright © 2011-2022 走看看