Codeforces Round 937 (Div. 4)

44 阅读10分钟

(今天刚补完G,感觉不错的一场)。

传送门

分析

A:A: AA语法题,判断即可

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long 
#define lowbit(x) x&(-x)
#define x first
#define y second

#define IOS ios::sync_with_stdio(false);cin.tie(nullptr),cout.tie(nullptr); 
#define two(x) __builtin_popcount(x)
using namespace std;
typedef pair<ll,ll> PII;
const int mod=998244353;
ll qmi(ll a,ll b){ll res=1ll;while(b){if(b&1) res=res*a;b>>=1;a=(a)*(a);}return res;}
//ll qmi(ll a,ll b,ll mod){ll res=1ll;while(b){if(b&1) res=(res%mod)*a%mod;b>>=1;a=(a%mod)*(a%mod)%mod;}return res%mod;}
//const int N=2001020;
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;} //最大公约数 
//ll fact[N],infact[N];
//void c(ll mod){fact[0]=infact[0]=1;for(ll i=1;i<=N-5;i++){fact[i]=(i%mod*fact[i-1]%mod)%mod;infact[i]=(infact[i-1]%mod)*(qmi(i,mod-2,mod)%mod)%mod;}}
//ll C(ll a,ll b,ll mod){return ((fact[a]%mod*infact[b]%mod)%mod*(infact[a-b]%mod)%mod)%mod;}//组合数 
//void creat(int x){heap[++cnt]=x;int t=cnt;while(t>1 && heap[t]<heap[t/2]){swap(heap[t/2],heap[t]);t/=2;}heap[t]=x;} 

void solve(){
	int a,b,c;
	cin>>a>>b>>c;
	if(a<b && b<c) cout<<"STAIR\n";
	else if(a<b && c<b) cout<<"PEAK\n";
	else cout<<"NONE\n";	 
}

int main(){
	IOS
	int t;
	t=1;
	cin>>t; 
	while(t--) solve();
	return 0;
}

B:B: BB很容易发现一个规律,就是关于行列模4的一个规律(具体见代码)。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long 
#define lowbit(x) x&(-x)
#define x first
#define y second

#define IOS ios::sync_with_stdio(false);cin.tie(nullptr),cout.tie(nullptr); 
#define two(x) __builtin_popcount(x)
using namespace std;
typedef pair<ll,ll> PII;
const int mod=998244353;
ll qmi(ll a,ll b){ll res=1ll;while(b){if(b&1) res=res*a;b>>=1;a=(a)*(a);}return res;}
//ll qmi(ll a,ll b,ll mod){ll res=1ll;while(b){if(b&1) res=(res%mod)*a%mod;b>>=1;a=(a%mod)*(a%mod)%mod;}return res%mod;}
//const int N=2001020;
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;} //最大公约数 
//ll fact[N],infact[N];
//void c(ll mod){fact[0]=infact[0]=1;for(ll i=1;i<=N-5;i++){fact[i]=(i%mod*fact[i-1]%mod)%mod;infact[i]=(infact[i-1]%mod)*(qmi(i,mod-2,mod)%mod)%mod;}}
//ll C(ll a,ll b,ll mod){return ((fact[a]%mod*infact[b]%mod)%mod*(infact[a-b]%mod)%mod)%mod;}//组合数 
//void creat(int x){heap[++cnt]=x;int t=cnt;while(t>1 && heap[t]<heap[t/2]){swap(heap[t/2],heap[t]);t/=2;}heap[t]=x;} 

void solve(){
	int a,b,c;
	cin>>a>>b>>c;
	if(a<b && b<c) cout<<"STAIR\n";
	else if(a<b && c<b) cout<<"PEAK\n";
	else cout<<"NONE\n";	 
}

int main(){
	IOS
	int t;
	t=1;
	cin>>t; 
	while(t--) solve();
	return 0;
}

C:C: CC其实就是个考察scanfscanf读入数字和字符分开的知识点。注意特判以下12:xx12:xx,然后就结束了。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long 
#define lowbit(x) x&(-x)
#define x first
#define y second

#define IOS ios::sync_with_stdio(false);cin.tie(nullptr),cout.tie(nullptr); 
#define two(x) __builtin_popcount(x)
using namespace std;
typedef pair<ll,ll> PII;
const int mod=998244353;
ll qmi(ll a,ll b){ll res=1ll;while(b){if(b&1) res=res*a;b>>=1;a=(a)*(a);}return res;}
//ll qmi(ll a,ll b,ll mod){ll res=1ll;while(b){if(b&1) res=(res%mod)*a%mod;b>>=1;a=(a%mod)*(a%mod)%mod;}return res%mod;}
//const int N=2001020;
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;} //最大公约数 
//ll fact[N],infact[N];
//void c(ll mod){fact[0]=infact[0]=1;for(ll i=1;i<=N-5;i++){fact[i]=(i%mod*fact[i-1]%mod)%mod;infact[i]=(infact[i-1]%mod)*(qmi(i,mod-2,mod)%mod)%mod;}}
//ll C(ll a,ll b,ll mod){return ((fact[a]%mod*infact[b]%mod)%mod*(infact[a-b]%mod)%mod)%mod;}//组合数 
//void creat(int x){heap[++cnt]=x;int t=cnt;while(t>1 && heap[t]<heap[t/2]){swap(heap[t/2],heap[t]);t/=2;}heap[t]=x;} 

void solve(){
	int h,m;
	scanf("%02d:%02d",&h,&m);
	if(h==0){
		printf("%02d:%02d AM\n",h+12,m);
	}else{
		if(h<12){
			printf("%02d:%02d AM\n",h,m);
		}else if(h==12){
			printf("%02d:%02d PM\n",h,m);
		}else printf("%02d:%02d PM\n",h-12,m);
	}
}

int main(){
	//IOS
	int t;
	t=1;
	cin>>t; 
	while(t--) solve();
	return 0;
}

D:D: DD挺有含金量,我们不妨考虑,从小往大去枚举所有满足二进制的约数,然后一一除去,再看剩下的这个数是不是也满足二进制的规律,满足的话就结束,否则全试除完了,要是还是不满足,就输出NONO

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long 
#define lowbit(x) x&(-x)
#define x first
#define y second

#define IOS ios::sync_with_stdio(false);cin.tie(nullptr),cout.tie(nullptr); 
#define two(x) __builtin_popcount(x)
using namespace std;
typedef pair<ll,ll> PII;
const int mod=998244353;
ll qmi(ll a,ll b){ll res=1ll;while(b){if(b&1) res=res*a;b>>=1;a=(a)*(a);}return res;}
//ll qmi(ll a,ll b,ll mod){ll res=1ll;while(b){if(b&1) res=(res%mod)*a%mod;b>>=1;a=(a%mod)*(a%mod)%mod;}return res%mod;}
//const int N=2001020;
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;} //最大公约数 
//ll fact[N],infact[N];
//void c(ll mod){fact[0]=infact[0]=1;for(ll i=1;i<=N-5;i++){fact[i]=(i%mod*fact[i-1]%mod)%mod;infact[i]=(infact[i-1]%mod)*(qmi(i,mod-2,mod)%mod)%mod;}}
//ll C(ll a,ll b,ll mod){return ((fact[a]%mod*infact[b]%mod)%mod*(infact[a-b]%mod)%mod)%mod;}//组合数 
//void creat(int x){heap[++cnt]=x;int t=cnt;while(t>1 && heap[t]<heap[t/2]){swap(heap[t/2],heap[t]);t/=2;}heap[t]=x;} 

bool check(int x){
	string s=to_string(x);
	int ans1=0;
	for(int i=0;i<s.size();i++){
		if(s[i]=='0' || s[i]=='1') ans1++;
	}
	return ans1==(int)s.size();
}
void solve(){
	int n;
	cin>>n;
	int t=n;
	if(check(t)){
		cout<<"YES\n";
		return;
	}
	for(int i=2;i<=n/i;i++){
		if(t<i) break;
		if(check(i)){
			if(t%i==0){
				while(t%i==0){
					t/=i;
					if(check(t)){
						cout<<"YES\n";
						return;
					}
				}
			}
		}
	}
//	cout<<t<<"\n";
	if(check(t)) cout<<"YES\n";
	else cout<<"NO\n";
}

int main(){
	IOS
	int t;
	t=1;
	cin>>t; 
	while(t--) solve();
	return 0;
}

E:E: EEWAWA麻了,开始搞什么魔幻二分做法,然后WAWA,其实这题就是纯暴力题,里面加个小的优化就是我们找长度为l的最多出现的串用mapmap即可。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long 
#define lowbit(x) x&(-x)
#define x first
#define y second

#define IOS ios::sync_with_stdio(false);cin.tie(nullptr),cout.tie(nullptr); 
#define two(x) __builtin_popcount(x)
using namespace std;
typedef pair<ll,ll> PII;
const int mod=998244353;
ll qmi(ll a,ll b){ll res=1ll;while(b){if(b&1) res=res*a;b>>=1;a=(a)*(a);}return res;}
//ll qmi(ll a,ll b,ll mod){ll res=1ll;while(b){if(b&1) res=(res%mod)*a%mod;b>>=1;a=(a%mod)*(a%mod)%mod;}return res%mod;}
//const int N=2001020;
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;} //最大公约数 
//ll fact[N],infact[N];
//void c(ll mod){fact[0]=infact[0]=1;for(ll i=1;i<=N-5;i++){fact[i]=(i%mod*fact[i-1]%mod)%mod;infact[i]=(infact[i-1]%mod)*(qmi(i,mod-2,mod)%mod)%mod;}}
//ll C(ll a,ll b,ll mod){return ((fact[a]%mod*infact[b]%mod)%mod*(infact[a-b]%mod)%mod)%mod;}//组合数 
//void creat(int x){heap[++cnt]=x;int t=cnt;while(t>1 && heap[t]<heap[t/2]){swap(heap[t/2],heap[t]);t/=2;}heap[t]=x;} 
int n;
const int N=500010;
int primes[N];
bool st[N]={false};
int cnt=0;

map<string,int> mp;
void solve(){
	cin>>n;
	string s;
	cin>>s;
	//if(!st[n]) cout<<n<<"\n";
	//else{
		vector<int> v;
		for(int i=1;i<=n;i++){
			if(n%i==0){
				v.push_back(i);
			}
		}
		//v.push_back(n);
		//int l=0,r=v.size()-1;
		for(int i=0;i<v.size();i++){
			int mid=i;
			int m=0;
			mp.clear();
			while(m!=s.size()){
				string t=s.substr(m,v[mid]);
				mp[t]++;
				m+=v[mid];
			}
			int maxn=0;
			for(auto it:mp){
				maxn=max(maxn,it.y);
			}
			string te;
			for(auto it:mp){
				if(it.y==maxn){
					te=it.x;
					break;
				}
			}
			int ans=0;
			m=0;
			while(m!=(int)s.size()){
				for(int i=m;i<m+te.size();i++){
					if(te[i-m]!=s[i]) ans++;
				}
				m+=(int)te.size();
			}
			if(ans<=1){
				cout<<v[i]<<"\n";
				break;
			}
		}
		
//	}
}

int main(){
	IOS
	int t;
	t=1;
	cin>>t; 
//	prime(N-10);
	while(t--) solve();
	return 0;
}

F:F: FF是个很有意思的数学题,使用二叉树的性质,我们肯定是先考虑有两个儿子的节点,把这些层数都确定完了,我们再去考虑一个儿子的,那么我们可以想一下,假如深度是hh,假设第hh层还剩kk个位置没有放两个儿子的节点,那么肯定是先填满这kk个节点,如果不够就往下加就行了,如果够,那我们的深度就没必要加了,这个kk也好算,就是总的节点第hh层的节点数nhn_h-(总节点数nn-前h1h-1层总和),即 k=nh(ni=0h1nik=n_h-(n-\sum\limits_{i=0}^{h-1}n_i),至于1-1的情况就很好判断了。因为无论怎么增加,我们最后一层两个儿子节点数和一个儿子节点数之和是不变的。所以这个必须与00个儿子的节点数相同,否则就输出1-1

(感觉说的很清楚了)。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long 
#define lowbit(x) x&(-x)
#define x first
#define y second

#define IOS ios::sync_with_stdio(false);cin.tie(nullptr),cout.tie(nullptr); 
#define two(x) __builtin_popcount(x)
using namespace std;
typedef pair<ll,ll> PII;
const int mod=998244353;
ll qmi(ll a,ll b){ll res=1ll;while(b){if(b&1) res=res*a;b>>=1;a=(a)*(a);}return res;}
//ll qmi(ll a,ll b,ll mod){ll res=1ll;while(b){if(b&1) res=(res%mod)*a%mod;b>>=1;a=(a%mod)*(a%mod)%mod;}return res%mod;}
//const int N=2001020;
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;} //最大公约数 
//ll fact[N],infact[N];
//void c(ll mod){fact[0]=infact[0]=1;for(ll i=1;i<=N-5;i++){fact[i]=(i%mod*fact[i-1]%mod)%mod;infact[i]=(infact[i-1]%mod)*(qmi(i,mod-2,mod)%mod)%mod;}}
//ll C(ll a,ll b,ll mod){return ((fact[a]%mod*infact[b]%mod)%mod*(infact[a-b]%mod)%mod)%mod;}//组合数 
//void creat(int x){heap[++cnt]=x;int t=cnt;while(t>1 && heap[t]<heap[t/2]){swap(heap[t/2],heap[t]);t/=2;}heap[t]=x;} 
int n;
const int N=500010;
int primes[N];
bool st[N]={false};
int cnt=0;

map<string,int> mp;
void solve(){
	int a,b,c;
	cin>>a>>b>>c;
	int i=1;
	while(qmi(2,i)-1<a){
		i++;
	} 
	if(a==0){
		i=0;
	}
	//cout<<i<<"\n";
	int depth=i;
	int up=qmi(2,i)-1-a;
	//cout<<up<<" ";
	int down=0;
	if(i!=0){
		down=2*qmi(2,i-1)-2*up;
	}else down=1;
	if(b<=up){
		//up-=b;
		if(up+down!=c){
			cout<<"-1\n";
		}else cout<<depth<<"\n";
	}else{
		b-=up;
		int add=0;
		if(b%(up+down)==0) depth+=b/(up+down);
		else depth+=b/(up+down)+1;
		if(up+down!=c){
			cout<<"-1\n";
		}else cout<<depth<<"\n";
	}
}

int main(){
	IOS
	int t;
	t=1;
	cin>>t; 
//	prime(N-10);
	while(t--) solve();
	return 0;
}

G:G: GG赛时没来得及看,(EE卡死我了草)。后来看了下,GG是一个相当相当有意思的状压dpdp。很适合新手做题,我也是听RR佬讲了一半会了,感觉这些基础的状压dpdp都是一个套路,考虑dp[i][j]dp[i][j]ii表示一个二进制0101串,就是11表示取哪些数和00表示不取哪些数。jj是表示最后一次操作我们取的是哪个数。然后写写写然后TLE33TLE33,后来发现哦,要优化,要把对每个串符合要求的都存进vectorvector里面,对不起,然后过了,具体转移方程见代码,很清晰。

#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define ll long long 
#define lowbit(x) x&(-x)
#define x first
#define y second

#define IOS ios::sync_with_stdio(false);cin.tie(nullptr),cout.tie(nullptr); 
#define two(x) __builtin_popcount(x)
using namespace std;
typedef pair<ll,ll> PII;
const int mod=998244353;
ll qmi(ll a,ll b){ll res=1ll;while(b){if(b&1) res=res*a;b>>=1;a=(a)*(a);}return res;}
//ll qmi(ll a,ll b,ll mod){ll res=1ll;while(b){if(b&1) res=(res%mod)*a%mod;b>>=1;a=(a%mod)*(a%mod)%mod;}return res%mod;}
//const int N=2001020;
ll gcd(ll x,ll y){return y?gcd(y,x%y):x;} //最大公约数 
//ll fact[N],infact[N];
//void c(ll mod){fact[0]=infact[0]=1;for(ll i=1;i<=N-5;i++){fact[i]=(i%mod*fact[i-1]%mod)%mod;infact[i]=(infact[i-1]%mod)*(qmi(i,mod-2,mod)%mod)%mod;}}
//ll C(ll a,ll b,ll mod){return ((fact[a]%mod*infact[b]%mod)%mod*(infact[a-b]%mod)%mod)%mod;}//组合数 
//void creat(int x){heap[++cnt]=x;int t=cnt;while(t>1 && heap[t]<heap[t/2]){swap(heap[t/2],heap[t]);t/=2;}heap[t]=x;} 
const int N=16;
bool dp[1<<N][N]={false};
struct mes{
	string a,b;
}name[N];
int n;
int cnt[1<<N];
vector<int> v[N];
void solve(){
	cin>>n;
	vector<int> v[N];
	for(int i=0;i<(1<<n);i++){
		for(int j=0;j<n;j++){
			dp[i][j]=false;
		} 
	}
	for(int i=0;i<n;i++){
		dp[1<<i][i]=true;
	}
	for(int i=0;i<n;i++){
		cin>>name[i].a>>name[i].b;
	}
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			if(j!=i && (name[j].a==name[i].a || name[j].b==name[i].b)){
				v[i].push_back(j);
				v[j].push_back(i);
			}
		}
	}
	for(int i=1;i<(1<<n);i++){
		for(int j=0;j<n;j++){
			if((i>>j&1)){
				for(int k=0;k<v[j].size();k++){
					if((i-(1<<j))>>v[j][k]&1){
						dp[i][j]|=dp[i-(1<<j)][v[j][k]];
					}
				}
			}
		}
	}
	int res=0;
	int ans=0; 
	for(int i=0;i<(1<<n);i++){
		for(int j=0;j<n;j++){
			if(dp[i][j]){
				ans++;
				res=max(cnt[i],res);
			}
		} 
	}
	cout<<n-res<<"\n";
}

int main(){
	IOS
	//cout<<("-5"<"-6");
	int t;
	t=1;
	cin>>t;
	for(int i=0;i<(1<<N);i++){
		cnt[i]=two(i);
	}
	//scanf("%d",&t);
	while(t--) solve();
	return 0;
}