• Educational Codeforces Round 109 (Rated for Div. 2)


    D. Armchairs

    题目描述

    点此看题

    解法

    很多贪心都是不行的,反例基本上都举得出来,我不知道模拟费用流能不能做。

    话不多说,直接进入正解。这道题是一个不对等匹配的问题,但是我们所熟悉的模型是相等个数的东西来匹配,这个经典问题是可以排序解决的。那么我们可以考虑枚举 (a_i=0) 参与匹配的集合 (S),然后依次匹配即可。

    选出这个集合可以 (dp),设 (dp[i][j]) 表示考虑到 (i) 已经匹配了 (j)(1) 的最小花费,随便转移就可以 (O(n^2))

    #include <cstdio>
    #include <vector>
    #include <cstring>
    using namespace std;
    const int M = 5005;
    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,a[M],dp[M][M];vector<int> v;
    int Abs(int x) {return x>0?x:-x;}
    signed main()
    {
    	n=read();v.push_back(0);
    	for(int i=1;i<=n;i++)
    	{
    		a[i]=read();
    		if(a[i]) v.push_back(i);
    	}
    	memset(dp,0x3f,sizeof dp);
    	dp[0][0]=0;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=0;j<v.size();j++)
    		{
    			int x=v[j];
    			dp[i][j]=min(dp[i][j],dp[i-1][j]);
    			if(!a[i] && j>0)
    				dp[i][j]=min(dp[i][j],dp[i-1][j-1]+Abs(i-v[j]));
    		}
    	}
    	printf("%d
    ",dp[n][v.size()-1]);
    }
    

    E. Assimilation IV

    题目描述

    点此看题

    解法

    我觉得我就是被概率洗脑了,有时候算算方案数也挺好的。

    一看就是要求每个点的期望,对于点 (i) 我们考虑他怎么才算被覆盖,如果存在 (p_jleq n+1-a(j,i)) 则合法。但是这个好像不是很好算,正难则反,我们考虑什么时候不合法,(forall p_j>n+1-a(j,i)) 则不合法,拿 (1) 减去不合法的概率即可。

    求不合法的概率可以求排列 (p) 的方案数除以总方案数,我们用 (cnt) 数组统计 (n+1-a(j,i)),那么填第一个位置可以有 (cnt[0]) 种方案,填第二个位置有 (cnt[1]+cnt[0]-1) 种方案,填第三个位置有 (cnt[2]+cnt[1]+cnt[0]-2) 种方案 (...) 以此类推。

    #include <cstdio>
    #include <iostream>
    using namespace std;
    const int M = 50005;
    const int MOD = 998244353;
    #define int long long
    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,m,inv,ans,a[25][M],cnt[M];
    int qkpow(int a,int b)
    {
    	int r=1;
    	while(b>0)
    	{
    		if(b&1) r=r*a%MOD;
    		a=a*a%MOD;
    		b>>=1;
    	}
    	return r;
    }
    signed main()
    {
    	n=read();m=read();inv=1;
    	for(int i=1;i<=n;i++)
    		inv=inv*qkpow(i,MOD-2)%MOD;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=m;j++)
    			a[i][j]=read();
    	for(int i=1;i<=m;i++)
    	{
    		for(int j=0;j<=n;j++) cnt[j]=0;
    		for(int j=1;j<=n;j++) cnt[n+1-a[j][i]]++;
    		int tmp=inv;
    		for(int j=0,s=0;j<n;j++)
    		{
    			s+=cnt[j];
    			tmp=tmp*s%MOD;
    			s=max(0ll,s-1);
    		}
    		ans=(ans+1-tmp)%MOD;
    	}
    	printf("%lld
    ",(ans+MOD)%MOD);
    }
    

    F. Goblins And Gnomes

    题目描述

    点此看题

    解法

    转化一下题意就知道这题是有关最小链覆盖,那么用调整法建出网络流模型:源连出点、如果两点直接存在边那么出点连入点、入点连汇点,这张图的最大流就是 (n-)最小链覆盖,我们要通过删除入点或者出点来使得 (i) 时刻的最小链覆盖 (>i)

    删点可能带来最大流的减少,那么我们能通过删某个点让最大流减少 (1) 吗?是可以的,因为对于一对匹配的点总存在一个使得删去它能让最大流建 (1),如果不能的话说明这两个点都存在替代的匹配点,那么最大匹配一定会增加 (1),矛盾。

    这个结论说明了任意删点都可以,因为任意网络都能存在这种合法的删除点,那么我们预处理出需要删的点(直接暴力枚举即可),然后搞一个 (dp_{i,j}) 表示前 (i) 个时刻删了 (j) 个点的最大得分,最后输出一下 (dp) 路径即可。

    时间复杂度 (O(n^3sqrt n)),因为 ( t dinic) 跑二分图单次是 (O(nsqrt n)) 的。

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <queue>
    using namespace std;
    const int M = 2005;
    const int inf = 0x3f3f3f3f;
    #define int long long
    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,m,k,t,mx,a[M],b[M],d[M],del[M];
    int tot,S,T,f[M],dis[M],dp[55][55],pre[55][55];
    struct edge
    {
    	int v,c,next;
    }e[2*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 bfs()
    {
    	for(int i=S;i<=T;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=f[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(e[i].c,ept));
    			if(!tmp) continue;
    			ept-=tmp;
    			e[i].c-=tmp;
    			e[i^1].c+=tmp;
    			flow+=tmp;
    			if(!ept) break;
    		}
    	}
    	return flow;
    }
    int get()
    {
    	S=0;T=2*n+1;tot=1;
    	for(int i=S;i<=T;i++) f[i]=0;
    	for(int i=1;i<=m;i++)
    	{
    		int u=a[i],v=b[i];
    		add(u+n,v,1);//x is in / x+n is out;
    	}
    	for(int i=1;i<=n;i++)
        {
            if(!del[i+n]) add(S,i+n,1);
            if(!del[i]) add(i,T,1);
        }
    	int res=0;
    	while(bfs()) res+=dfs(S,inf);
    	return res;
    }
    void print(int x,int y)
    {
    	if(!x) return ;
    	print(x-1,pre[x][y]);
    	for(int i=pre[x][y]+1;i<=y;i++)
    	{
    		if(d[i]>n) printf("%lld ",d[i]-n);
    		else printf("%lld ",-d[i]);
    	}
    	printf("0 ");
    }
    signed main()
    {
    	n=read();m=read();k=read();
    	for(int i=1;i<=m;i++)
    		a[i]=read(),b[i]=read();
    	mx=get();
    	for(int i=1;i<=mx;i++)
    		for(int j=1;j<=2*n;j++)
    			if(!del[j])
    			{
    				del[j]=1;
    				if(get()==mx-i)//we can delete j to reduce the maxmatch
    				{
    					d[++t]=j;
    					break;
    				}
    				del[j]=0;
    			}
    	memset(dp,-0x3f,sizeof dp);
    	dp[0][0]=0;
    	for(int i=1;i<=k;i++)
    	{
    		int x=read(),y=read();
    		for(int j=0;j<=t;j++)
    		{
    			if(i-j>=n-mx) continue;//illegal
    			for(int k=0;k<=j;k++)//we choose k now
    				if(dp[i][j]<dp[i-1][j-k]+max(0ll,x-k*y))
    				{
    					dp[i][j]=dp[i-1][j-k]+max(0ll,x-k*y);
    					pre[i][j]=j-k;
    				}
    		}
    	}
    	int p=0;
    	for(int i=0;i<=t;i++)
    		if(dp[k][i]>dp[k][p])
    			p=i;
    	printf("%lld
    ",k+p);
    	print(k,p);
    }
    
  • 相关阅读:
    php环境搭建
    smarty模板基础
    ThinkPHP模板的知识
    php调用API支付接口 可个人使用,无需营业执照(使用第三方接口,调用的天工接口。)
    HTML插入地图的方法
    phpcms调用语句
    phpcms基础循环
    js鼠标拖动(转载)
    js源生ajax
    php读取xml文件并处理
  • 原文地址:https://www.cnblogs.com/C202044zxy/p/14787374.html
Copyright © 2020-2023  润新知