Codeforces Round 959 sponsored by NEAR (Div. 1 + Div. 2)

可惜还是只能 VP。好像这场的 E 重了所以有很多人打差评?

A. Diverse Game

简单的。直接将每个数 +1 就行了,如果为 n×m 就变为 1

B. Fun Game

一开始读错题了。考虑分别找到 s,t 中第一个 1 的位置,若 s 中的位置大于等于 t 中的位置那么有解,反之无解。记 s 中第一个 1 位置为 pos,考虑每次操作选取区间都形如 [l,l+pos1],手玩可以发现这个操作可以代替其他所有操作,所以只要 pos 前面没有要修改成 1 的地方就行了。

C. Hungry Games

计数题,考虑 dp。设 dpi 表示以 i 为起点的非法子串数,考虑填表法,做一遍前缀和,每次转移时可以二分得到第一个使 [i,j] 区间和大于 x 的位置 j,从 i1 处转移 dpj=dpj+dpi1,如果到了一个 i 使得 sumi1+xsumn 就 break,答案就是 n×(n+1)2i=0n1dpi。注意 dp 初值赋为 1
这个其实和官解差不多的。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll N=2*114514,M=1919810;
ll T;
ll n,m,k,a[N],sum[N],dp[N]; //以i开头的不合法子串个数? 
string s,t;
void solve(){
	cin>>n>>k;
	dp[0]=1;
	for(int i=1;i<=n;++i) cin>>a[i],sum[i]=sum[i-1]+a[i],dp[i]=1;
	ll pos=1,ans=n*(n+1)/2;
	for(int i=1;i<=n;++i){
		if(sum[i-1]+k>=sum[n]) break;
		ll j=upper_bound(sum+i,sum+n+1,sum[i-1]+k)-sum;
		ans-=dp[i-1],dp[j]+=dp[i-1];
	}
	cout<<ans<<'\n';
}//红温了 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin>>T;
	while(T--) solve();
	return 0;
} 

D. Funny Game

明显 x 越小能连的边就越多,所以可以考虑从大到小枚举 x 建边。建树肯定要加一个并查集来判断,根据鸽巢原理(或者手玩得到),这 x+1 个点中一定存在一对能连边的点,那么我们便枚举一个点 i,开数组记录下模 x 相同且不连通的点,然后并查集维护连通性,最后再倒着输出就可以了。

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pi pair<ll,ll>
#define fi first
#define se second
const ll N=2*114514,M=1919810;
ll T;
ll n,m,k,a[N],f[N],p[N];
ll find(ll x){
	return x==f[x]?x:f[x]=find(f[x]);
}
vector <pi> out;
void solve(){
	cin>>n;
	for(int i=1;i<=n;++i) cin>>a[i],f[i]=i;
	out.clear();
	cout<<"YES\n";
	for(int i=n-1;i>=1;--i){
		ll u=0,v=0;
		for(int j=0;j<=n;++j) p[j]=0;
		for(int j=1;j<=n;++j){
			if(j!=find(j)) continue;
			ll ux=a[find(j)]%i;
			if(p[ux]!=0){
				u=p[ux],v=find(j);
				break; 
			}
			p[ux]=find(j);
		}
		//cout<<u<<" "<<v<<'\n';
		out.push_back({u,v});
		ll x=find(u),y=find(v);
		if(x!=y) f[y]=x;
	}
	for(int i=out.size()-1;i>=0;--i) cout<<out[i].fi<<" "<<out[i].se<<'\n';
}//红温了 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin>>T;
	while(T--) solve();
	return 0;
} 

E. Wooden Game

看了题解。我们发现对于一棵树,假设它足够大,只要不断删除叶节点再删除更大的子树就能凑出二进制上的每一位,从而使或的和最大,也就是说答案是和树的形态无关,只和大小有关的。

然后就显然了。从高到低枚举答案在二进制上的每一位,然后枚举哪颗树可以凑出这一位。令当前位数为 i 对于一棵树,如果凑不出就 continue,否则若答案此为也为 0,那么就让答案与上 1<<i;若答案为 1 的话就可以让 i 后面的所有位都与上 1,这样的答案就是最优的。

复杂度 O(nlogV)

点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pi pair<ll,ll>
#define fi first
#define se second
const ll N=1145140,M=1919810;
ll T;
ll n,m,k,x,a[N];
bool cmp(ll x,ll y){
	return x>y;
}
void solve(){
	cin>>k;
	for(int i=1;i<=k;++i){
		cin>>a[i];
		for(int j=1;j<a[i];++j) cin>>x;
	}
	sort(a+1,a+k+1,cmp);
	ll ans=0;
	for(int i=1;i<=k;++i){
		for(int j=24;j>=0;--j){
			ll f1=ans>>j&1,f2=a[i]>>j&1;
			if(f2==0) continue;
			if(f1==0) ans|=1<<j;
			else{
				ans|=(1<<j)-1;
				break;
			}
		}
	}
	cout<<ans<<'\n';
}//红温了 
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0);
	cin>>T;
	while(T--) solve();
	return 0;
} 

F. Stardew Valley

没看了

posted @   和蜀玩  阅读(314)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· AI 智能体引爆开源社区「GitHub 热点速览」
· 写一个简单的SQL生成工具
· Manus的开源复刻OpenManus初探

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示