ABC 的一些 FG

abc 212f

看到 query 题,显然预处理。预处理从一个点跳 \(2^k\) 次到哪里。query 时分讨情况。

点击查看代码
#include <bits/stdc++.h>

using namespace std;

#define de(x) cout<<#x<<"="<<x<<endl
#define mp(x,y) make_pair(x,y)

using ll = long long;

const int N = 1e5+5;

int n,m,q;
int a[N],b[N],s[N],t[N];
vector<pair<int,int> > g[N];
int fa[22][N];

void solve(int x,int y,int z){
	auto it=lower_bound(g[y].begin(),g[y].end(),mp(x,-1));
	if (it==g[y].end()){
		cout<<y<<endl;
		return;
	}
	int fst=(*it).second;
	if (z<=s[fst]){
		cout<<y<<endl;
		return;
	}
	else if (z<=t[fst]){
		cout<<a[fst]<<" "<<b[fst]<<endl;
		return;
	}
	// more than one city
	for (int i=21; ~i; i--){
		if (t[fa[i][fst]]<z){
			fst=fa[i][fst];
		}
	}
	int cc=b[fst];
	auto itt=lower_bound(g[cc].begin(),g[cc].end(),mp(t[fst],-1));
	if (itt==g[cc].end()){
		cout<<cc<<endl;
		return;
	}
	int fstt=(*itt).second;
	if (z<=s[fstt]){
		cout<<cc<<endl;
		return;
	}
	cout<<a[fstt]<<" "<<b[fstt]<<endl;
	return;
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin>>n>>m>>q;
	for (int i=0; i<m; i++){
		cin>>a[i]>>b[i]>>s[i]>>t[i];
		g[a[i]].push_back({s[i],i});
	}
	for (int i=1; i<=n; i++){
		sort(g[i].begin(),g[i].end());
	}
	for (int i=0; i<m; i++){
		fa[0][i]=i;
		auto it=lower_bound(g[b[i]].begin(),g[b[i]].end(),mp(t[i],-1));
		if (it!=g[b[i]].end()){
			fa[0][i]=(*it).second;
		}
	}
	for (int i=1; i<22; i++){
		for (int j=0; j<m; j++){
			fa[i][j]=fa[i-1][fa[i-1][j]];
		}
	}
	while (q--){
		int x,y,z;
		cin>>x>>y>>z;
		// time x city y end z
		solve(x,y,z);
	}
	return 0;
}

// don't waste time!!!

abc 213g

挺好玩。

定义 \(f_{msk}\)\(msk\) 里面连通的方案数(其余边没有)。算这个东西有点困难,再设计一个?

定义 \(g_{msk}\) 为选了 \(msk\) 这个集合,不管它连不连通。这个东西很好算,\(2^e\),其中 \(e\) 是左右端点都在 \(msk\) 里边的个数。

怎么用 \(g\) 表示 \(f\)\(f_{msk}=g_{msk}-不满足的\)\(不满足的=\sum_{T\subsetneq S} f(T)\times g(S-T)\) (\(-\) 是去掉啊)。然后这个从前往后算就可以了。

怎么用 \(f,g\) 来表示答案?(定义 \(V=\{1\cdots N\}\)\(ans_{k}=\sum_{\{1,k\}\subseteq S\subseteq V} f(S)\times g(V-S)\)

点击查看代码
#include <bits/stdc++.h>

using namespace std;

#define de(x) cout<<#x<<"="<<x<<endl

using ll = long long;

const int N = 17;
const ll mod = 998244353;

int n,m;
bool ff[N][N];
ll f[1<<N],g[1<<N],res[1<<N];

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin>>n>>m;
	for (int i=0; i<m; i++){
		int u,v;
		cin>>u>>v;
		u--;
		v--;
		ff[u][v]=ff[v][u]=1;
	}
	for (int i=0; i<(1<<n); i++){
		g[i]=1ll;
		for (int j=0; j<n; j++){
			for (int k=j+1; k<n; k++){
				if ((i>>j)&1 && (i>>k)&1 && ff[j][k]){
					(g[i]*=2ll)%=mod;
				}
			}
		}
	//	cout<<g[i]<<endl;
	}
	for (int i=0; i<(1<<n); i++){
		if (i==0){
			f[i]=1;
			continue;
		}
		if (!(i&1)){
			f[i]=0;
			continue;
		}
		f[i]=g[i];
		for (int j=i-(i&-i); j; j=(j-1)&i){
			// ss
			f[i]=(f[i]-g[i^j]*f[j]%mod+mod)%mod;
		}
	//	cout<<"f[i]: "<<f[i]<<endl;
	}
	for (int i=1; i<n; i++){
		for (int j=0; j<(1<<n); j++){
			if ((j>>i)&1){
		//		cout<<"?"<<endl;
				(res[i]+=f[j]*g[(1<<n)-j-1])%=mod;
			}
		}
		cout<<res[i]<<endl;
	}
	return 0;
}

// don't waste time!!!

abc 214f

如果没有重复的,\(dp_{i}=\sum_{j\le i-2} dp_j\)\(j\) 从后往前,如果遇到一样的了,就 break,防止重复。\(O(26N)\)

点击查看代码
#include <bits/stdc++.h>

using namespace std;

#define de(x) cout<<#x<<"="<<x<<endl

using ll = long long;

const int N = 2e5+5;
const ll mod = 1e9+7;

ll dp[N];

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	string s;
	cin>>s;
	int n=s.size();
	s=" "+s;
	dp[0]=1;
	for (int i=2; i<=n+1; i++){
		for (int j=i-2; j>=0; j--){
			(dp[i]+=dp[j])%=mod;
			if (s[i-1]==s[j]){
				break;
			}
		}
//		cout<<dp[i]<<endl;
	}
	ll ans=0;
	for (int i=2; i<=n+1; i++){
		(ans+=dp[i])%=mod;
	}
	cout<<ans<<endl;
	return 0;
}

// don't waste time!!!

abc 216f

先从大到小 sort。

\(dp_{i,j}\) 表示前 \(i\) 个,\(\max A-\sum B\)\(j\)

点击查看代码
#include <bits/stdc++.h>

using namespace std;

#define de(x) cout<<#x<<"="<<x<<endl

using ll = long long;

const int N = 5e3+3;
const ll mod = 998244353;

int n,a[N],b[N],id[N],c[N],d[N];
ll dp[N][N]; 

bool cmp(int x,int y){
	return a[x]>a[y];
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin>>n;
	for (int i=0; i<n; i++){
		cin>>a[i];
	}
	for (int i=0; i<n; i++){
		cin>>b[i];
		id[i]=i;
	}
	sort(id,id+n,cmp);
	for (int i=0; i<n; i++){
		c[i]=a[id[i]],d[i]=b[id[i]];
		if (c[i]>=d[i]){
			dp[i][c[i]-d[i]]++;
		}
	}
	for (int i=0; i<n-1; i++){
		for (int j=0; j<N; j++){
			(dp[i+1][j]+=dp[i][j])%=mod;
			if (j>=d[i+1]){
				(dp[i+1][j-d[i+1]]+=dp[i][j])%=mod;
			}
		}
	}
	ll ans=0;
	for (int i=0; i<N; i++){
		(ans+=dp[n-1][i])%=mod;
	}
	cout<<ans<<endl;
	return 0;
}

// don't waste time!!!

abc 215g

看了 Editorial。

Editorial 里面就一个式子吧,\(ans=E[\sum_{i-1}^C X]=\sum_{i=1}^C E[X_i]=\sum_{i=1}^C \frac{\binom{N}{K}-\binom{N-n_i}{K}}{\binom{N}{K}}\)。按个数分组,\(O(N\sqrt{N})\)

点击查看代码
#include <bits/stdc++.h>

using namespace std;

#define de(x) cout<<#x<<"="<<x<<endl

using ll = long long;

const int N = 2e5+5;
const ll mod = 998244353;

ll pw(ll a,ll b){
	ll res=1;
	while (b){
		if (b&1){
			res=res*a%mod;
		}
		a=a*a%mod;
		b>>=1;
	}
	return res;
}

ll Inv(ll x){
	return pw(x,mod-2);
}

ll f[N],inv[N],invf[N];

void init(){
	f[0]=1;
	for (ll i=1; i<N; i++){
		f[i]=f[i-1]*i%mod;
	}
	inv[1]=1;
	for (int i=2; i<N; i++){
		inv[i]=Inv(i);
	}
	invf[0]=1;
	invf[1]=1;
	for (int i=2; i<N; i++){
		invf[i]=invf[i-1]*inv[i]%mod;
	}
}

ll C(ll x,ll y){
	if (x<y || x<0 || y<0){
		return 0;
	}
	return f[x]*invf[y]%mod*invf[x-y]%mod;
}

ll n,c[N>>2],ans[N>>2];
map<ll,ll> cnt,cnt2;

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	init();
	cin>>n;
	for (int i=1; i<=n; i++){
		cin>>c[i];
		cnt[c[i]]++;
	}
	for (auto p : cnt){
		cnt2[p.second]++;
	}
	for (auto p : cnt2){
		ll x=p.first,y=p.second;
		for (int i=1; i<=n; i++){
			(ans[i]+=(C(n,i)-C(n-x,i)+mod)*y%mod)%=mod;
		}
	}
	for (int i=1; i<=n; i++){
		cout<<ans[i]*Inv(C(n,i))%mod<<endl;
	}
	return 0;
}

// don't waste time!!!

abc 216g

差分约束板板题。

\(i\)\(i+1\),最多 \(1\) 个 0,限制条件:\(l-1\)\(r\),最多 \(r-l+1-x\) 个。

点击查看代码
#include <bits/stdc++.h>

using namespace std;

#define de(x) cout<<#x<<"="<<x<<endl

using ll = long long;

const int N = 2e5+5;

int n,m,dis[N],vis[N];
vector<pair<int,int> > g[N];

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin>>n>>m;
	for (int i=0; i<n; i++){
		g[i].push_back({i+1,1});
		g[i+1].push_back({i,0});
	}
	for (int i=0; i<m; i++){
		int l,r,x;
		cin>>l>>r>>x;
		g[l-1].push_back({r,r-l+1-x});
	}
	memset(dis,0x3f,sizeof dis);
	dis[0]=0;
	priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> q;
	q.push({0,0});
	while (!q.empty()){
		int x=q.top().second;
		q.pop();
		if (vis[x]){
			continue;
		}
		vis[x]=1;
		for (auto p : g[x]){
			int y=p.first;
			int w=p.second;
			if (dis[y]>dis[x]+w){
				dis[y]=dis[x]+w;
				q.push({dis[y],y});
			}
		}
	}
	for (int i=0; i<n; i++){
		cout<<((dis[i+1]-dis[i])^1)<<" ";
	}
	cout<<endl;
	return 0;
}

// don't waste time!!!

abc 217f

区间 dp,\(dp_{i,j}\) 表示 \([i,j]\) 处理完方案数。\(dp_{i,j}=\sum dp_{i+1,k-1}\times dp_{k+1,j}\times \binom{j-i+1}{k-i+1}\)

点击查看代码
#include <bits/stdc++.h>

using namespace std;

#define de(x) cout<<#x<<"="<<x<<endl

using ll = long long;

const int N = 4e2+2;
const ll mod = 998244353;

int n,m;
ll dp[N][N];
bool f[N][N];
ll c[N][N];

void init(){
	c[0][0]=1;
	for (int i=1; i<N; i++){
		c[i][0]=1;
		for (int j=1; j<N; j++){
			c[i][j]=(c[i-1][j]+c[i-1][j-1])%mod;
		}
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	init();
	cin>>n>>m;
	n+=n;
	for (int i=0; i<m; i++){
		int a,b;
		cin>>a>>b;
		f[a][b]=f[b][a]=1;
	}
	for (int i=n+1; i; i--){
		dp[i][i-1]=1;
		for (int j=i+1; j<=n; ++++j){
			for (int k=i+1; k<=j; ++++k){
				if (f[i][k]){
					int a=(j-i+1)/2,b=(k-i+1)/2;
					(dp[i][j]+=dp[i+1][k-1]*dp[k+1][j]%mod*c[a][b]%mod)%=mod;
				}
			}
		}
	}
	cout<<dp[1][n]<<endl;
	return 0;
}

// don't waste time!!!

abc 217g

\(dp_{i,j}\) 表示前 \(i\) 个分 \(j\) 组方案数。显然 \(dp_{i,j}=dp_{i-1,j-1}+dp_{i-1,j}\times(j-\lfloor \frac{i-1}{m} \rfloor)\)。(\(i\) 单不单独成一组)。

点击查看代码
#include <bits/stdc++.h>

using namespace std;

#define de(x) cout<<#x<<"="<<x<<endl

using ll = long long;

const int N = 5e3+3;
const ll mod = 998244353;

int n,m;
ll dp[N][N];

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin>>n>>m;
	dp[0][0]=1;
	for (int i=1; i<=n; i++){
		for (int j=1; j<=i; j++){
			(dp[i][j]+=dp[i-1][j-1])%=mod;
			(dp[i][j]+=(j-(i-1)/m)*dp[i-1][j])%=mod;
		}
	} 
	for (int i=1; i<=n; i++){
		cout<<dp[n][i]<<endl;
	}
	return 0;
}

// don't waste time!!!

abc 218f

除了删掉 \(1\)\(N\) 的最短路径上的点,其他没有影响。最短路径上的重新 bfs 一次即可。

点击查看代码
#include <bits/stdc++.h>

using namespace std;

#define de(x) cout<<#x<<"="<<x<<endl

using ll = long long;

const int N = 4e2+2;

int n,m,dis[N],u[N*N],v[N*N];
int mp[N][N],ans[N*N];
pair<int,int> p[N];

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin>>n>>m;
	for (int i=1; i<=m; i++){
		cin>>u[i]>>v[i];
		mp[u[i]][v[i]]=i;
	}
	queue<int> q;
	memset(dis,-1,sizeof dis);
	q.push(1);
	dis[1]=0;
	while (!q.empty()){
		int x=q.front();
		q.pop();
		for (int y=1; y<=n; y++){
			if (mp[x][y] && dis[y]==-1){
				dis[y]=dis[x]+1;
				p[y]={x,mp[x][y]};
				q.push(y);
			}
		}
	}
	vector<int> ms;
	int cur=n;
	while (cur!=1&&cur!=0){
		ms.push_back(p[cur].second);
		cur=p[cur].first;
	}
	for (int i=1; i<=m; i++){
		ans[i]=dis[n];
	}
	for (auto eg : ms){
		mp[u[eg]][v[eg]]=0;
		queue<int> q;
		memset(dis,-1,sizeof dis);
		dis[1]=0,q.push(1);
		while (!q.empty()){
			int x=q.front();
			q.pop();
			for (int y=1; y<=n; y++){
				if (mp[x][y] && dis[y]==-1){
					dis[y]=dis[x]+1,q.push(y);
				}
			}
		}
		ans[eg]=dis[n],mp[u[eg]][v[eg]]=eg;
	}
	for (int i=1; i<=m; i++){
		cout<<ans[i]<<endl;
	}
	return 0;
}

// don't waste time!!!

abc 218g

确定了结束在哪一个叶子,就确定了整条路经。对每一个叶子预处理出中位数,然后树形 dp。

预处理可以用树状数组。

点击查看代码
#include <bits/stdc++.h>

using namespace std;

#define de(x) cout<<#x<<"="<<x<<endl

using ll = long long;

const int N = 2e5+5;

int n,a[N];
vector<int> g[N];
int dp[N][2];
int bit[N],val[N];

void M(int x,int ad){
	while (x<=n){
		bit[x]+=ad;
		x+=x&-x;
	}
}

int Q(int x){
	int res=0;
	while (x){
		res+=bit[x];
		x-=x&-x;
	}
	return res;
}

int fa[N],vl[N],f[N];

int bs(int x){
	int l=-1,r=n+1;
	while (l+1<r){
		int mid=l+r>>1;
		if (Q(mid)<x){
			l=mid;
		}
		else{
			r=mid;
		}
	}
	return r;
}

void dfs(int v,int d){
	M(a[v],1);
	f[v]=1;
	for (auto u : g[v]){
		if (u!=fa[v]){
			fa[u]=v;
			dfs(u,d+1);
			f[v]=0;
		}
	}
	if (f[v]){
		if (d&1){
			vl[v]=val[bs((d+1)/2)];
		}
		else{
			vl[v]=(val[bs(d/2)]+val[bs(d/2+1)])/2;
		}
	}
	M(a[v],-1);
} 

void dfss(int v){
	if (f[v]){
//		cout<<v<<": "<<vl[v]<<endl;
		dp[v][0]=dp[v][1]=vl[v];
		return;
	}
	dp[v][0]=-1e9-5;
	dp[v][1]=1e9+5;
	for (auto u : g[v]){
		if (u!=fa[v]){
			dfss(u);
			dp[v][0]=max(dp[v][0],dp[u][1]);
			dp[v][1]=min(dp[v][1],dp[u][0]);
		}
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);

	cin>>n;
	set<int> st;
	for (int i=1; i<=n; i++){
		cin>>a[i];
		st.insert(a[i]);
	}
	map<int,int> mp;
	int cnt=0;
	for (auto u : st){
		mp[u]=++cnt;
		val[cnt]=u;
	}
	for (int i=1; i<=n; i++){
		a[i]=mp[a[i]];
	}
	for (int i=1; i<n; i++){
		int u,v;
		cin>>u>>v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(1,1);
	dfss(1);
	cout<<dp[1][0]<<endl;
	return 0;
}

// don't waste time!!!

补题去了。

posted @ 2023-08-14 16:21  SFlyer  阅读(18)  评论(0编辑  收藏  举报