首页 > 其他分享 >AT_abc_326

AT_abc_326

时间:2023-10-29 10:55:51浏览次数:29  
标签:abc return int flow pos read 326 inline

好久没打 abc 了,久违的 rated 一场比赛,结果被 D 创飞了。

\(9\) 分钟把 ABC 题切掉,然后看 D 题,觉得是个简单的模拟,错了 \(5\) 次,直接把我人整懵了,一看题目 字符a,b,c只出现一次,我以为是 字符a,b,c至少出现一次,妈妈生的。

E

求期望,有个很显然的东西,就是 \(ans=\sum_{i=1}^{n} a_i\times p_i\),\(p_i\) 是丢骰子丢到 \(i\) 的期望次数。
而且 \(p_i=\dfrac{1}{n}\sum_{j=0}^{i-1}p_j\)。

这个东西是可以线性求的。

int n,a[N];
inline int ksm(int a,int b){
    int res=1;
    while(b){
        if(b&1)res=res*a%mod;
        a=a*a%mod;
        b>>=1;
    }
    return res;
}
signed main(){
    n=read();
    up(i,1,n)a[i]=read();
    int p=ksm(n,mod-2);
    int res=0;
    up(i,1,n){
        res=(res+p*a[i])%mod;
        p=(p+p*ksm(n,mod-2))%mod;
    }
    cout<<res;
    return 0;
}

F

一道搜索好题。

一眼就可以看到 \(n\le 80\),看起来直接暴搜不是很能过的样子,考虑优化。

因为每一次都要转向,所以可以可以考虑把 \(x\) 轴和 \(y\) 轴分开计算。

这样,时间复杂度就是 \(2\times 2^{40}\)。

还是不够,继续优化,因为直到初始状态和最终状态,所以可以考虑双向搜索优化。

最后输出答案需要注意,我们记录的信息是 \(x\) 和 \(y\) 的正负,转化成 LR 需要记录前一位的信息。

int n,sx,sy;
map<int,string>mpx;
map<int,string>mpy;
map<int,int>mp;
int a[500];
vector<int>x,y;
inline void dfsx(int i,int pos,string s){
    if(i==x.size()/2){
        mpx[pos]=s;
        return;
    }
    dfsx(i+1,pos+x[i],s+"1");
    dfsx(i+1,pos-x[i],s+"0");
}
bool fl=0;
inline void dfsx2(int i,int pos,string s){
    if(i==x.size()){
        if(!mpx.count(sx-pos))return;
        mpx[sx]=mpx[sx-pos]+s;
		fl=1;
		return;
    }
	dfsx2(i+1,pos+x[i],s+"1");
    if(fl)return;
    dfsx2(i+1,pos-x[i],s+"0");
    if(fl)return;
}
inline void dfsy(int i,int pos,string s){
    if(i==y.size()/2){
        mpy[pos]=s;
        return;
    }
    dfsy(i+1,pos+y[i],s+"1");
    dfsy(i+1,pos-y[i],s+"0");
}
inline void dfsy2(int i,int pos,string s){
    if(i==y.size()){
        if(!mpy.count(sy-pos))return;
        mpy[sy]=mpy[sy-pos]+s;
		fl=1;
		return;
    }
	dfsy2(i+1,pos+y[i],s+"1");
    if(fl)return;
    dfsy2(i+1,pos-y[i],s+"0");
    if(fl)return;
}
inline void print(){
    puts("Yes");
    vector<int>ans;
    int i=0,j=0;
    while(i<mpy[sy].size()||j<mpx[sx].size()){
        if(i<mpy[sy].size())ans.push_back(mpy[sy][i]-'0'),i++;
        if(j<mpx[sx].size())ans.push_back(mpx[sx][j]-'0'),j++;
    }
    int la=0;
	 up(i,0,ans.size()-1) {
		if (ans[i]) {
			if (la==0) cout<<"L",la=1;
			else if (la==1) cout<<"R",la=0;
			else if (la==2) cout<<"R",la=1;
			else if (la==3) cout<<"L",la=0; 
		}
		else {
			if (la==0) cout<<"R",la=3;
			else if (la==1) cout<<"L",la=2;
			else if (la==2) cout<<"L",la=3;
			else if (la==3) cout<<"R",la=2; 
		}
	}
}
signed main(){
	n=read();sx=read();sy=read();
    up(i,1,n){
        a[i]=read();
        if(i&1)y.push_back(a[i]);
        else x.push_back(a[i]);
    }
    dfsx(0,0,"");
    dfsx2(x.size()/2,0,"");
    fl=0;
    dfsy(0,0,""); 
    dfsy2(y.size()/2,0,"");
    if(mpx.count(sx)&&mpy.count(sy))print();
    else puts("No");
    return 0;
}

G

看上去就很网络流。

因为 \(L_{i,j}\le 5\) 所以我们需要的点数很少。

我们先把所有的价值都加进去,然后求最小割,这个网络流的图是很容易建的,但是有几个细节地方要注意,如果当前节点不满足,那么比这个节点等级高的点同样不满足,所以之间可以连一条 \(inf\) 的边,
同样的,如果一个条件不满足而获得了这个成就的价值,那么同样的要连一条权值为 \(inf\) 的边。

int n,m;
int c[N],a[N];
struct Dinic{
	struct edge{
		int u,v,cap,flow;
	};
	vector<edge>edges;
	vector<int>g[N];
	int cur[N],d[N];
	bool vis[N];
	inline void add(int u,int v,int cap){
		edges.push_back({u,v,cap,0});
		edges.push_back({v,u,0,0});
		int t=edges.size();
		g[u].push_back(t-2);
		g[v].push_back(t-1);
	}
	inline bool bfs(int s,int t){
		memset(vis,0,sizeof vis);
		queue<int>q;
		q.push(s);
		d[s]=0;vis[s]=1;
		while(q.size()){
			int u=q.front();q.pop();
			for(auto i:g[u]){
				auto e=edges[i];
				if(!vis[e.v]&&e.cap>e.flow){
					vis[e.v]=1;
					d[e.v]=d[u]+1;
					q.push(e.v);
				}
			}
		}
		return vis[t];
	}
	inline int dfs(int u,int a,int t){
		if(u==t||a==0)return a;
		int flow=0,f;
		for(int &i=cur[u];i<g[u].size();i++){
			auto& e=edges[g[u][i]];
			if(d[u]+1==d[e.v]&&(f=dfs(e.v,min(a,e.cap-e.flow),t))>0){
				e.flow+=f;
				edges[g[u][i]^1].flow-=f;
				flow+=f;
				a-=f;
				if(a==0)break;
			}
		}
		return flow;
	}
	inline int maxflow(int s,int t){
		int flow=0;
		while(bfs(s,t)){
			memset(cur,0,sizeof cur);
			flow+=dfs(s,inf,t);
		}
		return flow;
	}
}E;
int ans=0;
signed main(){
	n=read();m=read();
    int s=5*n+m,t=5*n+m+1;
    up(i,0,n-1) {
        int c=read();
        up(j,0,3){
            E.add(5*i+j,5*i+j+1,c*j);
            E.add(5*i+j+1,5*i+j,inf);
        } 
        E.add(5*i+4,t,c*4);
    }
    up(i,1,m)a[i]=read(),ans+=a[i];
    int x;
    up(i,0,m-1){
        up(j,0,n-1){
            x=read()-1;
            E.add(5*n+i,5*j+x,inf);
        }
        E.add(s,5*n+i,a[i+1]);
    }
    ans-=E.maxflow(s,t);
    cout<<ans;
    return 0;
}

标签:abc,return,int,flow,pos,read,326,inline
From: https://www.cnblogs.com/LiQXing/p/17795596.html

相关文章

  • ABC326
    此前也没有写一整场比赛题解的习惯,那就从现在开始吧。D:简单的一道题,直接搜就行了。代码:#include<bits/stdc++.h>usingnamespacestd;typedeflonglongll;template<classT>boolchmax(T&a,constT&b){if(a<b){a=b;returntrue;}returnfalse;}template<c......
  • AtCoder Beginner Contest 326
    A-2UP3DOWN(abc326A)题目大意100楼层,一次可以上最多两层,或下最多三层。给定两楼层,问能否一次到达。解题思路比较大小,然后判断其差是是不是在\(2\)或\(3\)内即可。神奇的代码#include<bits/stdc++.h>usingnamespacestd;usingLL=longlong;intmain(void){......
  • ABC326
    上次说我的写法low的人的AT号在这里!!(我又来提供low算法了。从D开始。T4我们把\(\text{A}\)看成\(1\),把\(\text{B}\)看成\(2\),把\(\text{C}\)看成\(3\)。那么就可以想到状压,然后把每一行和每一列的情况状态即可。#include<bits/stdc++.h>usingnamespacestd;......
  • AtCoder Beginner Contest 326 题解
    首先,\(\text{HappyBirthdaytome!}\)A-2UP3DOWN常规ABCA...//If,oneday,Ifinallymanagetomakemydreamsareality...//Iwonder,willyoustillbetherebymyside?#include<bits/stdc++.h>#defineIOSios::sync_with_stdio(false)#defineTI......
  • AtCoder Beginner Contest(abc) 310
    B-StrictlySuperior难度:⭐题目大意给定n个商品的价格,每个商品还有若干个属性,请问是否存在一个商品是另外一个商品的上位品;上位品的定义分两种,一是价格相同,但是商品A的属性不仅包括了商品B的属性,还比商品B多了至少一个属性;二是如果两商品的属性相同,但是......
  • ABC219H Candles
    很显然的区间dp+费用提前计算。但是每个位置上的\(a_i\)还有一个上限的机制,走到某个位置上时似乎还需要判断该\(a_i\)是否已被减完。但其实不需要,因为一旦选到负的\(a_i\),就一定不再是最优解了,所以我们可以将走到\(a_i\)不大于\(0\)的位置时的决策看作不选,否则看作选,那......
  • [ABC299G] Minimum Permutation
    ABC229G洛谷链接atcoder链接容易发现如果最终答案有两个相邻的数\(b_i,b_{i+1}\)满足\(b_i>b_{i+1}\)且\(b_i\)之后出现过,则显然可以找到另一个不劣的答案不满足这个性质先说一个错误的结论:从前往后考虑,用链表维护答案,对于加入的一个数\(a_i\),如果之前在\(a_j\)出现......
  • ABC219 H 区间dp 费用提前计算
    ABC219H跟关路灯很像。很容易注意到我们拿走的只能是一个区间,观察n的范围发现区间dp是个好想法。朴素的想法是定义\(f_{i,j,k,0/1}\)为拿走i到j里面的所有数,走了k秒,现在在i/j的方案数。然后发现k太大了。咱当时的想法是希望优化复杂度,把k去掉结果发现不能保证正确性。......
  • AtCoder Beginner Contest(abc) 309
    B-Rotate题目大意给定一个n*n的矩阵,要求把矩阵的最外围按照顺时针转动一个数据,输出转动后的矩阵;解题思路数据不大,暴力即可;神秘代码#include<bits/stdc++.h>#defineintlonglong#defineIOSios::sync_with_stdio(false);cin.tie(0);cout.tie(0);#def......
  • [ABC256E] Takahashi's Anguish
     题目 https://www.luogu.com.cn/problem/AT_abc256_e 图论题,是个环套树发现环上的边要取掉一条(min),其他的不用取https://www.luogu.com.cn/record/131488937......