Codeforces Round 924 (Div. 2)

不会 F 的场。

A

Code
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

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

	int t;
	cin>>t;
	while (t--){
		int a,b;
		cin>>a>>b;
		int f=0;
		if (a%2==0 && a/2!=b){
			f=1;
		}
		if (b%2==0 && b/2!=a){
			f=1;
		}
		if (f){
			cout<<"Yes\n";
		}
		else{
			cout<<"No\n";
		}
	}
	return 0;
}

B

去重二分。

Code
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

const int N = 2e5+5;

int n;

void solve(){
	cin>>n;
	vector<int> v;
	for (int i=0; i<n; i++){
		int x;
		cin>>x;
		v.push_back(x);
	}
	sort(v.begin(),v.end());
	v.erase(unique(v.begin(),v.end()),v.end());
	int ans=0;
	for (int i=0; i<v.size(); i++){
		int mx=v[i]+n-1;
		int l=i,r=v.size();
		while (l+1<r){
			int mid=l+r>>1;
			if (v[mid]>mx){
				r=mid;
			}
			else{
				l=mid;
			}
		}
		ans=max(ans,l-i+1);
	}
	cout<<ans<<"\n";
}

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

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

其实可以双指针的。

C

分别考虑是前一半还是后一半。发现 \(2k-2\mid n-x\)\(2k-2 \mid n+x-2\) 才可以。同时 \(k\ge x\)

Code
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

void solve(){
	ll n,x;
	cin>>n>>x;
	set<ll> st;
	ll y=n-x;
	for (ll i=1; i*i<=y; i++){
		if (y%i==0){
			if (i%2==0) st.insert(i);
			if ((y/i)%2==0) st.insert(y/i);
		}
	}
	y=n+x-2;
	for (ll i=1; i*i<=y; i++){
		if (y%i==0){
			if (i%2==0) st.insert(i);
			if ((y/i)%2==0) st.insert(y/i);
		}
	}
	int cnt=0;
	for (auto u : st){
		if ((u+2)/2>=x){
			cnt++;
		}
	}
	cout<<cnt<<"\n";
}

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

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

D

\(\mathcal{O}(N+\sum c)\) 做法。记录少了一个组会少掉多少战斗值。

Code
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

const int N = 2e5+5;

ll n,b,X,c[N],mn[N];

void solve(){
	cin>>n>>b>>X;
	ll tot=0;
	for (int i=1; i<=n; i++){
		cin>>c[i];
		tot+=c[i];
	}
	for (int i=1; i<=tot; i++){
		mn[i]=0;
	}
	ll sum=0;
	for (int i=1; i<=n; i++){
		ll qs=c[i]*(c[i]-1)/2;
		sum+=qs;
	//	cout<<c[i]<<"::"<<qs<<"\n"; 
		for (ll j=c[i]-1; j>=1; j--){
			ll _x=c[i]/j;
			ll y=c[i]%j;
			ll x=j-y;
	//		assert(x+y==j);
			ll it=x*_x*(c[i]-_x)+y*(_x+1)*(c[i]-_x-1);
			it/=2;
	//		cout<<_x<<","<<x<<","<<y<<","<<qs<<","<<it<<"\n";
			mn[j]+=qs-it;
			qs=it;
		}
	//	cout<<",,,"<<"\n";
	}
	//cout<<sum<<"!\n";
	ll ans=0;
	for (ll i=tot; i>=1; i--){
		ans=max(ans,sum*b-(i-1)*X);
		sum-=mn[i-1];
	}
	cout<<ans<<"\n";
}

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

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

E

你考虑最少 \(sum\) 也得有 \((x\%y)\times n\)\(y\mid sum-(x\%y)\times n\)

你考虑你已经有了答案数组,然后数组每项都减去 \((x\%y)\),再除以 \(y\),这个数列一定是 (从 \(x\) 开始的若干项)+(一堆 \(12345\cdots\)组成的,中间以 \(0\) 间隔)。答案不存在是 \(sum<(x\%y)*\times n\)\((sum-(x\%y)\times n)\%y\neq 0\) 或后面放不下了。

可以 \(dp_i\) 设为至少有做少个位置,才可以放得下 \(i\)\(y\)。然后 \(dp_i\) 可以转移:\(dp_i=min\{dp_{i-a_j}+j+1\}\)\(a_j\) 是第 \(j\) 个三角形数。然后就 \(\mathcal{O}(N\sqrt{N})\) 预处理完。

Code
#include <bits/stdc++.h>

using namespace std;

using ll = long long;

const int N = 2e5+5;

int a[500];
int dp[N],ans[N],pth[N];

void init(){
	a[1]=1;
	int tot;
	for (tot=2; a[tot-1]<N; tot++){
		a[tot]=a[tot-1]+tot;
	}
	tot--;
	memset(dp,0x3f,sizeof dp);
	dp[0]=0;
	for (int i=1; i<N; i++){
		for (int j=1; j<=tot && a[j]<=i; j++){
			if (dp[i]>dp[i-a[j]]+j+1){
				dp[i]=dp[i-a[j]]+j+1;
				pth[i]=j;
			}
		}
	}
}

void solve(){
	ll n,x,y,s;
	cin>>n>>x>>y>>s;
	ll md=x%y;
	ll mn=md*n;
	if (s<mn){
		cout<<"NO\n";
		return;
	}
	if ((s-mn)%y!=0){
		cout<<"NO\n";
		return;
	}
	ll nd=(s-mn)/y;
	for (ll i=0; i<=n; i++){
		if (i==0 && x!=md){
			continue;
		}
		// 1~i: from 1
		ll sum=(x+x+(i-1)*y)*i/2;
		sum=(sum-i*md)/y;
		if (i==0){
			sum=0;
		}
		if (sum>nd){
			break;
		}
		ll rm=nd-sum;
		if (dp[rm]>(n-i)){
			continue;
		}
		// rm is good
		ans[1]=x;
		for (int j=2; j<=i; j++){
			ans[j]=ans[j-1]+y;
		}
		int tot=i;
		int cur=rm;
		while (cur){
			int p=pth[cur];
			ans[++tot]=md;
			for (ll j=1; j<=p; j++){
				ans[++tot]=j*y+md;
			}
			cur=cur-a[p];
		}
		while (tot<n){
			ans[++tot]=md;
		}
		cout<<"YES\n";
		for (int i=1; i<=n; i++){
			cout<<ans[i]<<" ";
		}
		cout<<"\n";
		//
		return;
	}
	cout<<"NO\n";
}

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

	init();
	int t;
	cin>>t;
	while (t--){
		solve();
	}
	return 0;
}
posted @ 2024-02-11 20:30  SFlyer  阅读(114)  评论(0编辑  收藏  举报