一些題目

abc308G

比較 scrambled egg 吧。

引理:若 \(x<y<z\),那麽 \(\min\{x⊕y,y⊕z\}<x⊕z\)。換句話説,blackboard 上有用的只有相鄰的數。

證明:加入考慮到了第 \(i\) 位。若 \(x \& (1<<i),y\& (1<<i),z \& (1<<i)\) 不同為 \(1\),那麽要麽是 \(0,0,1\) 要麽是 \(0,1,1\)。前者 \(x⊕y<x⊕z\),後者 \(y⊕z<x⊕z\)。而 \(x<y<z\),所以不可能一直同爲 \(1\),所以引理成立。

同樣,若 \(x\le y\le z\),那麽 \(\min\{x⊕y,y⊕z\}\le x⊕z\)

只需要用 set 維護就可以了。

#include <bits/stdc++.h>

using namespace std;

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

using ll = long long;

int q;
multiset<int> nums;
multiset<int> xors;

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

	cin>>q;
	while (q--){
		int ty,x;
		cin>>ty;
		if (ty!=3){
			cin>>x;
		}
		if (ty==1){
			nums.insert(x);
			auto it=nums.lower_bound(x);
			int l=*prev(it),r=*next(it);
			if (it!=nums.begin() && next(it)!=nums.end()){
				xors.erase(xors.find(l^r));
			}
			if (it!=nums.begin()){
				xors.insert(l^x);
			}
			if (next(it)!=nums.end()){
				xors.insert(x^r);
			}
		}
		else if (ty==2){
			auto it=nums.lower_bound(x);
			int l=*prev(it),r=*next(it);
			if (it!=nums.begin() && next(it)!=nums.end()){
				xors.insert(l^r);
			}
			if (it!=nums.begin()){
				xors.erase(xors.find(l^x));
			}
			if (next(it)!=nums.end()){
				xors.erase(xors.find(x^r));
			}
			nums.erase(nums.find(x));
		}
		else{
			cout<<*(xors.begin())<<endl;
		}
	}
	return 0;
}

// 413!413!413!

abc307G

比較 scrambled egg 吧。怎麽評分 \(2330\),虛高。

很顯然一個加一,一個減一,sum 是不變的。於是根據條件,可以確定所有數是哪些數。

假如有一個數是 \(x\),有 \(cnt\) 個,可以 dp 如下:

\(dp_{i,j}\) 表示 \(1\sim i\) 中有 \(j\)\(x\) 的最小步數。這樣可以算出來 \(i+1\) 沒有動之前是什麽。

轉移很簡單。

#include <bits/stdc++.h>

using namespace std;

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

using ll = long long;

const int N = 5e3+3;

ll n,sum;
ll a[N],s[N],x,f,cnt;
ll dp[N][N];

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

	cin>>n;
	for (int i=1; i<=n; i++){
		cin>>a[i];
		s[i]=s[i-1]+a[i];
		sum+=a[i];
	}
	x=sum/n;
	cnt=n-abs(sum-x*n);
	f=((sum-x*n)<0?-1:1);
	memset(dp,0x3f,sizeof dp);
	dp[0][0]=0;
	for (int i=0; i<=n; i++){
		for (int j=max(0ll,i-(n-cnt)); j<=min(i*1ll,cnt); j++){
			ll ad=s[i]-j*x-(i-j)*(x+f);
			// to x
			dp[i+1][j+1]=min(dp[i+1][j+1],dp[i][j]+abs(a[i+1]+ad-x));
			// to x+f
			dp[i+1][j]=min(dp[i+1][j],dp[i][j]+abs(a[i+1]+ad-(x+f)));
		}
	}
	cout<<dp[n][cnt]<<endl;
	return 0;
}

// 413!413!413!

abc306G

顯然如果所有經過 \(1\) 的環的 \(\gcd \mid 10^{10^{100}}\),那麽 Yes 反之 No。當然,沒有環也是 No

然後我就不會了。感覺這個題解寫的還可以

#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,dep[N],f[N];
vector<int> g[N],rg[N];

void dfs(int v){
	for (auto u : g[v]){
		if (dep[u]==-1){
			dep[u]=dep[v]+1;
			dfs(u);
		}
	}
}

void dfsr(int v){
	f[v]=1;
	for (auto u : rg[v]){
		if (!f[u]){
			dfsr(u);
		}
	}
}

void solve(){
	cin>>n>>m;
	for (int i=0; i<n; i++){
		g[i].clear();
		rg[i].clear();
	}
	for (int i=0; i<m; i++){
		int u,v;
		cin>>u>>v;
		u--,v--;
		g[u].push_back(v);
		rg[v].push_back(u);
	}
	for (int i=0; i<n; i++){
		f[i]=0;
	}
	for (int i=1; i<n; i++){
		dep[i]=-1;
	}
	dep[0]=0;
	dfs(0);
	dfsr(0);
	for (int i=0; i<n; i++){
		if (!f[i]){
			dep[i]=-1;
		}
	}
	int gc=0;
	for (int i=0; i<n; i++){
		if (dep[i]==-1){
			continue;
		}
		for (auto j : g[i]){
			if (dep[j]!=-1){
				gc=__gcd(gc,abs(dep[i]-dep[j]+1));
			}
		}
	}
//	cout<<gc<<endl;
	if (!gc){
		cout<<"No"<<endl;
	}
	else{
		while (gc%2==0){
			gc/=2;
		}
		while (gc%5==0){
			gc/=5;
		}
		if (gc==1){
			cout<<"Yes"<<endl;
		}
		else{
			cout<<"No"<<endl;
		}
	}
}

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

	int t;
	cin>>t;
	while (t--){
		solve();
	}
	return 0;
}

// 413!413!413!
posted @ 2023-07-15 15:28  SFlyer  阅读(10)  评论(0编辑  收藏  举报