Codeforces Round 984 (Div. 3)题解记录(A~G)

比赛链接:https://codeforces.com/contest/2036

A. Quintomania

思路:数据范围小+题目清晰,题目要求左右两个数之差绝对值不等于\(5\)或这不等于\(7\),直接暴力即可,应该不会有人不知到内置函数\(abs\)

#include<iostream>
#include<queue>
#include<map>
#include<set>A~F
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                     long long 
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
		{
			ans = ans % mod * (x % mod) % mod;
		}
		x = x % mod * (x % mod) % mod;
		y >>= 1;
	}
	return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
void fio()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}
int main()
{
	fio();
	ll t;
	cin>>t;
	while(t--)
	{
		ll n;
		cin>>n;
		ll pd=0;
		ll o;
		for(ll i=1;i<=n;i++)
		{
			ll x;
			cin>>x;
			if(i>=2)
			{
				if(abs(o-x)==5||abs(o-x)==7)
				{
					o=x;
				continue;
				}
				pd=1;
			}
			o=x;
		}
		if(pd)
		cout<<"NO"<<endl;
		else 
		cout<<"YES"<<endl;
	}
	
}

B. Startup

思路:一开始看成选(总瓶子大于\(k\)\(k\)个瓶子放在\(n\)个货架上,然后货架上的牌子只能是同一种,感觉很难。
随后发现看错了,是总共有\(k\)个瓶子,然我放在\(n\)个货架上,且品牌得一样,于是直接贪心的把所有品牌对应的值进行累积,
然后进行排序,从大到小选取前\(min(n,牌子种类)\)个即可,本人为了方便直接用了优先对列

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                     long long 
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
		{
			ans = ans % mod * (x % mod) % mod;
		}
		x = x % mod * (x % mod) % mod;
		y >>= 1;
	}
	return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
void fio()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}
int main()
{
	fio();
	ll t;
	cin>>t;
	while(t--)
	{
		ll n,k;
		cin>>n>>k;
		map<ll,ll>mp;
		set<ll>q;
		priority_queue<ll>f;
		for(ll i=1;i<=k;i++)
		{
			ll x,y;
			cin>>x>>y;
			mp[x]+=y;
			q.insert(x);
		}
		for(auto j:q)
		{
			f.push(mp[j]);
		}
		ll ans=0;
		while(!f.empty())
		{
			ans+=f.top();
			f.pop();
			n--;
			if(n==0)
			break;

		}
		cout<<ans<<endl;
	}
}

C. Anya and 1100

思路:对于一个字符串有\(q\)次修改,问每次修改后是否存在\(1100\)字串
不妨想想,每次修改一个位置,最多会影响\(4\)个位置的可能,所以直接先暴力统计一开始的所有\(1100\)子串,然后每次修改进行区间\(1100\)变化统计
然后再修改原本的\(1100\)个数就可以了
赛事犯了个低级错误,一开始统计\(1100\)直接\(4\)\(4\)个查了。···

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                     long long 
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
		{
			ans = ans % mod * (x % mod) % mod;
		}
		x = x % mod * (x % mod) % mod;
		y >>= 1;
	}
	return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
void fio()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}
int main()
{
	fio();
	ll t;
	cin>>t;
	while(t--)
	{
		string f;
		cin>>f;
		ll n=f.size();
		ll q;
		cin>>q;
		ll ans=0;
		f='0'+f;
		for(ll i=1;i<=n-3;i++)
		{
			if(f[i]=='1'&&f[i+1]=='1'&&f[i+2]=='0'&&f[i+3]=='0')
			ans++;
		}
		while(q--)
		{
			ll x;
			char y;
			cin>>x>>y;
			if(n<4)
			{
				cout<<"NO"<<endl;
				continue;
			}
			else 
			{
				ll cnt=0;
				//cout<<n<<endl;
				for(ll i=x-3;i<=x;i++)
				{
					if(i>=1&&i+3<=n)
					{
						if(f[i]=='1'&&f[i+1]=='1'&&f[i+2]=='0'&&f[i+3]=='0')
						cnt++;
					}
				}
				f[x]=y;
				ll uo=0;
				for(ll i=x-3;i<=x;i++)
				{
					if(i>=1&&i+3<=n)
					{
						if(f[i]=='1'&&f[i+1]=='1'&&f[i+2]=='0'&&f[i+3]=='0')
						uo++;
					}
				}
				//cout<<cnt<<endl;
				uo-=cnt;
				ans+=uo;
				if(ans>0)
				cout<<"YES"<<endl;
				else 
				cout<<"NO"<<endl;
			}
		}
	}	
}

D. I Love 1543

思路:其实就是模拟下字符串有没有\(1543\),如何模拟?
首先外围走一圈顺时针是很有格式规定的,于是考虑递归写,然后终止条件可以画画,是目前最大行小于等于\(n/2\)或者目前最大列小于等于\(m/2\)
,然后每次缩一次上边界和下边界就可以了,统计的话为了方便直接重新进行字符串加和,然后再倍增一下,枚举\(0到size()/2-1\)最为第一个字符就可以了,注意防止越界哦

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                     long long 
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
		{
			ans = ans % mod * (x % mod) % mod;
		}
		x = x % mod * (x % mod) % mod;
		y >>= 1;
	}
	return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
void fio()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}
string f[4000];
ll n,m;
ll ans=0;
void ck(ll x,ll y,ll s,ll p)
{
	if(x<=n/2||y<=m/2)
	return ;
	string u="";
	for(ll j=p;j<=y;j++)
	{
		u+=f[s][j];
	}
	for(ll j=s+1;j<=x;j++)
	{
		u+=f[j][y];
	}
	for(ll j=y-1;j>=p;j--)
	{
		u+=f[x][j];
	}
	for(ll i=x-1;i>=s+1;i--)
	{
		u+=f[i][p];
	}
	//cout<<u<<endl;
	ll k=u.size()-1;
	u+=u;
	for(ll i=0;i<=k;i++)
	{
		if(i+3<=(ll)u.size()-1&&u[i]=='1'&&u[i+1]=='5'&&u[i+2]=='4'&&u[i+3]=='3')
		{
			ans++;
		}
	}
	//cout<<ans<<endl;
	ck(x-1,y-1,s+1,p+1);
}
int main()
{
	fio();
	ll t;
	cin>>t;
	while(t--)
	{
		//ll n,m;
		cin>>n>>m;
		for(ll i=1;i<=n;i++)
		{
			cin>>f[i];
			f[i]='0'+f[i];
		}
		ans=0;
		ck(n,m,1,1);
		cout<<ans<<endl;
	}	
}

E. Reverse the Rivers

思路:\(n*k<=10^5\),所以在\(main\)函数内定义二维数组,然后先按照题目要求进行处理或之和(两个数之或一定不变或者增加,所以或之和是不递减的,具有单调性),然后再用一个数组以列为第一维行为第二维统计每行对应的数,然后有\(q\)次询问,但是注意\(m<=10^5\),所以其实也就最多有\(m\)个约束。因为题目要求找到合理的最小序号,所以要用\(l,r\)双指针进行区间维护,对于\(<\),可以用\(lower_bound\)找到第一个大于等于\(y\)的行\(c\),然后\(c--\),取\(r=min(r,c)\),对于\(>\),可以用\(upper_bound\)直接找到对应的行\(c\),然后取\(l=max(l,c)\)即可,如果\(l>r\),输出\(-1\),否则输出\(l\)

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                     long long 
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
		{
			ans = ans % mod * (x % mod) % mod;
		}
		x = x % mod * (x % mod) % mod;
		y >>= 1;
	}
	return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
void fio()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}
int main()
{
	ll t;
	t=1;
	while(t--)
	{
		ll n,k,q;
		cin>>n>>k>>q;
		ll a[n+5][k+5];
		for(ll i=0;i<=n;i++)
		{
			for(ll j=0;j<=k;j++)
			{
				a[i][j]=0;
			}
		}
		for(ll i=1;i<=n;i++)
		{
			for(ll j=1;j<=k;j++)
			{
				cin>>a[i][j];
			}
		}
		//cout<<a[0][1]<<endl;
		ll b[k+5][n+5]={0};
		for(ll j=1;j<=k;j++)
		{
			for(ll i=1;i<=n;i++)
			{
				a[i][j]=(a[i][j]|a[i-1][j]);
				b[j][i]=a[i][j];
				//cout<<a[i][j]<<endl;
			}
		}
		//cout<<b[1][2]<<endl;
		while(q--)
		{
			ll m;
			cin>>m;
			ll l=1,r=n;
			for(ll i=1;i<=m;i++)
			{
				ll x,y;
				char f;
				cin>>x>>f>>y;
				if(f=='<')
				{
					ll u=lower_bound(b[x]+1,b[x]+1+n,y)-b[x];
					u--;
					r=min(r,u);
				}
				else 
				{
					ll u=upper_bound(b[x]+1,b[x]+1+n,y)-b[x];
					l=max(l,u);
				}
			}
			if(l>r)
			{
				cout<<-1<<endl;
			}
			else 
			cout<<l<<endl;
		}
	}
}

F. XORificator 3000

思路:赛时没考虑r<k时直接输出答案,一直WA2
其实对于一个从1开始的连续区间的异或和,其答案是有规律的
规律如下:
\(n%4==0\)
\(f(1,n)=n\)
\(n%4==1\)
\(f(1,n)=1\)
\(n%4==2\):
\(f(1,n)=n+1\)
\(n%4==3\):
\(f(1,n)=0\)
显然对于\(f(l,r)\)\(f(l,r)=f(1,r)^f(1,l-1)\)
随后如何处理不合理答案
其实容易发现对于\(2^i\)乘连续数的答案的异或之和会等于连续的数的异或之和乘以\(2^i\)
所以解决了\(2^i\)的问题然后是对于\(k\),他其实一直在异或自己,如果异或了自己偶数次,则为\(0\),否则为本身,这个的次数奇偶性等于区间\(2^i*b+k\),\(b\)的可能个数的奇偶性
最后处理好是否异或\(k\)就行了,注意特判情况\(r<k\)

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                     __int64
#define lowbit(x) (x & -x)
#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
		{
			ans = ans % mod * (x % mod) % mod;
		}
		x = x % mod * (x % mod) % mod;
		y >>= 1;
	}
	return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
void fio()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}
ll ck(ll r)
{
	if(r%4==0)
	{
	return r;
	}
		else if(r%4==1)
		{
			return 1;
		}
		else if(r%4==2)
		{
			return r+1;
		}
		else 
		{
			return 0;
		}
}
int main()
{
	ll t;
	cin>>t;
	while(t--)
	{
		ll l,r,f,k;
		cin>>l>>r>>f>>k;
		ll ans=0;
		ans=(ck(r)^ck(l-1));
		if(r<k)
		{
			cout<<ans<<endl;
			continue;
		}
		//cout<<ans<<endl;
		ll u=1<<f;
		ll l1=(l-k)/u+((l-k)%u>0);
		ll r1=(r-k)/u;
		ll op;
		op=ck(r1)^ck(l1-1);
		op*=u;
		ans^=op;
		if((r1-l1+1)%2==0)
		cout<<ans<<endl;
		else 
		{
		cout<<(ans^k)<<endl;
		}
	}
}

G. Library of Magic

思路:虽然上个思路错了,但是这次总算对了,因为问的次数不能超过150次
所以分类讨论
如果\(query(1,n)==0\)
代表着,存在三个是异或和为0,由于这个性质可以得出如果把1-n分成2得次幂的区间,区间询问大于0的个数一定会大于等于2
所以当个数等于2时,可以根据2进制最高位数相同异或为0,比左区间小得出一个区间是否存在两个数,然后另一个区间的询问数值就是答案之一,
然后二分还不知道答案的区间,可得出第二个答案,然后用区间询问异或这个答案就可得出第三个答案
当个数为3时,就二分出第一个答案,然后扩大下询问区间再得到一个异或和,用它与第一个答案异或得出第二个,以此类推得第三个
如果\(query(1,n)!=0\)
这个时候直接二分两次就可以了,直接得出两个答案,然后总区间异或去异或前两个答案,得出第三个答案
交互题确实写得比较难受

#include<iostream>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<algorithm>
#include<deque>
#include<cctype>
#include<string.h>
#include<math.h>
#include<time.h>
#include<random>
#include<stack>
#include<string>
#define ll                                     long long
#define lowbit(x) (x & -x)
//#define endl "\n"//                           交互题记得删除
using namespace std;
mt19937 rnd(time(0));
const ll mod = 998244353;
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
		{
			ans = ans % mod * (x % mod) % mod;
		}
		x = x % mod * (x % mod) % mod;
		y >>= 1;
	}
	return ans % mod % mod;
}
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
void fio()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}//对于三个数异或和为0,只可能在最高二进制数不同时才出现
ll q(ll x,ll y)
{
	cout<<"xor"<<" "<<x<<" "<<y<<endl;
	cout.flush();
	cin>>x;
	return x;
}
//ll a[2500000];
bool cmp(pair<ll,ll> x,pair<ll,ll> y)
{
    return x.first<y.first;
}
pair<ll,ll>a[50];
ll ef(ll l,ll r)
{
	while(l<r)
	{
		ll mid=(l+r)>>1;
		if(q(l,mid))
		{
			r=mid;
		}
		else 
		l=mid+1;
	}
	return r;
}
vector<ll>ans;
void solve()
{
	ans.clear();
	//map<ll,ll>mp;
ll n;
cin>>n;
set<ll>f;
ll o=0;
ll cnt=0;
ll d=q(1,n);
if(d==0)
{
for(ll i=0;i<=63;i++)
{
	if((1ll<<i)>n)break;
	//cout<<(1ll<<i)<<endl;
	if(q(1ll<<i,min(n,((1ll<<(i+1))-1))))
	{
		cnt++;
		a[cnt]={1ll<<i,min(n,((1ll<<(i+1))-1))};
	}
}
if(cnt==3)
{
	//cout<<cnt<<endl;
  //  sort(a+1,a+1+3,cmp);
    ll u=ef(a[1].first,a[1].second);
    d^=u;
    ans.push_back(u);
    ll j=q(a[1].first,a[2].second);
    j^=u;
    ans.push_back(j);
    d^=j;
    ans.push_back(d);
}
else if(cnt==2)
{
    ll op=0;
	sort(a+1,a+1+2,cmp);
    ll u=q(a[1].first,a[1].second);
    if(u<a[1].first)
    {
        ll j=ef(a[1].first,a[1].second);
        ans.push_back(j);
        ans.push_back(j^u);
        d^=u;
        ans.push_back(d);
    }
    else 
    {
        ans.push_back(u);
        d^=u;
        ll j=ef(a[2].first,a[2].second);
        ans.push_back(j);
        d^=j;
        ans.push_back(d);
    }
}
else 
{
    //ll op=0;
	ll k=ef(a[1].first,a[1].second);
    d^=k;
	ans.push_back(k);
	k=ef(k+1,a[1].second);
    d^=k;
	ans.push_back(k);
    ans.push_back(d);
}
}
else 
{
	ll k=ef(1,n);
	ans.push_back(k);
	d^=k;
	k=ef(k+1,n);
	ans.push_back(k);
	d^=k;
	ans.push_back(d);
}
//sort(ans.begin()),ans.end());
cout<<"ans";
for(auto j:ans)
{
	cout<<" "<<j;
}
cout<<endl;
}
int main()
{
	ll t;
	cin>>t;
	while(t--)solve();
}
posted @ 2024-11-03 01:52  长皆  阅读(803)  评论(0编辑  收藏  举报