Codeforces Round#633(Div。1)Solution(ABC)

コンテストリンク:https : //codeforces.com/contest/1338

A.パワードアディション

補題:正の整数\(a \)\([a、a + 2 ^ k-1] \)内で\(k \)以内任意の数値に変換できます

それは最終的に非減少シーケンスになるので、各要素の最小パディング量)\(S \)の最大値を取るだけでよいので、\(S \)より大きい2の最小整数乗は\(2 ^ k \ )、補題によると、答えは\(k \) qwqです

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll; const int inf=~0u>>2; ll read(){ll x; if(scanf("%lld",&x)==-1)exit(0); return x;}
#define int ll
int a[N];
int ans,n;
signed main(){
	int T; cin>>T;
	while(T--){
		cin>>n;
		repeat(i,0,n)cin>>a[i];
		int x=-inf;
		ans=0;
		repeat(i,0,n){
			if(a[i]<x)ans=max(ans,x-a[i]);
			x=max(x,a[i]);
		}
		int cnt=0;
		while(ans)ans>>=1,cnt++;
		cout<<cnt<<endl;
	}
	return 0;
}

B.エッジの重みの割り当て

ちょっとしたトリックは、2つのノード間のパスのxor合計です。つまり、パスxorと2つのノードからルートへのパスのxor合計です。

次数が1のノードをルートとします。利点は、2つのリーフのパスを確認する必要がないことです。ルートへのすべての葉のxor合計が0であることを確認するだけです(ヒントによると)。

最初のサブタスクは非常に単純です。答えは1または3のみで、2つのケースに分けられます(ルート次数が1かどうかを確認してください)

根の次数が1の場合、すべての葉の深さが均一で、答えは1です。

ルートの次数が1でない場合、すべての葉の深さのパリティは同じで、答えは1です。

2番目のサブタスクに関しては、1つの操作が激しくなった後、ほとんどの場合、2つのエッジの重みが等しくないことがわかりますが、多くのリーフがノードに接続されている場合、これらのエッジのエッジの重みは強制的に等しくされ、減算するだけです。できる

また、次数1のノードを根とする場合は、もともと葉であるため特別な判断が必要で、それ以外は特別な判断は不要です。

ここでは、次数1のノードをルートとしました

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll; const int inf=~0u>>2; ll read(){ll x; if(scanf("%lld",&x)==-1)exit(0); return x;}
//#define int ll
vector<int> a[N];
int rt,ans;
int deg[N],cnt[N],depth[N];
int flag=true;
void dfs(int x,int fa){
	for(auto p:a[x])
	if(p!=fa){
		depth[p]=depth[x]+1;
		dfs(p,x);
		cnt[x]+=deg[p]==1;
	}
	if(deg[x]==1 && depth[x]%2==1)flag=false;
	if(depth[x]==1)ans-=cnt[x];
	else ans-=max(cnt[x]-1,0);
}
signed main(){
	int n=read();
	repeat(i,0,n-1){
		int x=read()-1,y=read()-1;
		a[x].push_back(y); a[y].push_back(x);
		deg[x]++,deg[y]++;
	}
	repeat(i,0,n){
		if(deg[i]==1){rt=i; break;}
	}
	dfs(rt,-1);
	ans+=n-1;
	cout<<(flag?1:3)<<' '<<ans<<endl;
	return 0;
}

C.パーフェクトトリプル

最初にいくつか(バイナリ)をリストします

1 10 11
100 1000 1100
101 1010 1111
110 1011 1101
111 1001 1110
10000 100000 110000
10001 100010 110011
10010 100011 110001
10011 100001 110010
10100 101010 111110
...

何を見つけましたか?

そうです、私はそれを0231法則(霧)と呼びます。つまり、最初の列の数が決定された場合、2番目の列の数は次の方法で取得できます。最初に16進数に変換され、次に\([0,1,2 、3] \)は対応して\([0,2,3,1] \)になります

完璧です。最初の列の数は非常に規則的(多くの連続)で、3番目の列の数は最初の列xまたは 2番目の列によって取得されるため、水のタイトルは実際にはdiv1C、霧の位置に配置されます。

変数名を取得するのは本当に難しいので、スパイシーなチキンコードが警告します

#include <bits/stdc++.h>
using namespace std;
#define repeat(i,a,b) for(int i=(a),_=(b);i<_;i++)
#define repeat_back(i,a,b) for(int i=(b)-1,_=(a);i>=_;i--)
int cansel_sync=(ios::sync_with_stdio(0),cin.tie(0),0);
const int N=200010; typedef long long ll; const int inf=~0u>>2; ll read(){ll x; if(scanf("%lld",&x)==-1)exit(0); return x;}
#define int ll
int ss[4]={0,2,3,1};
int f(int x){
	if(x==0)return 0;
	return f(x/4)*4+ss[x%4];
}
signed main(){
	int T=read();
	while(T--){
		int n=read()-1; if(n<3){cout<<n+1<<endl; continue;}
		int p=n/3;
		int x;
		for(x=1;p>=0;p-=x,x*=4);
		x/=4; p+=x;
		if(n%3==0){cout<<p+x<<endl; continue;}
		int t1=x+p;
		int t2=f(t1);
		if(n%3==1)cout<<t2<<endl;
		else cout<<(t1^t2)<<endl;
	}
	return 0;
}

おすすめ

転載: www.cnblogs.com/axiomofchoice/p/12688806.html