首页 > 其他分享 >Codeforces Round 972 (Div. 2)题解记录

Codeforces Round 972 (Div. 2)题解记录

时间:2024-10-10 14:01:17浏览次数:10  
标签:cnt gcd ++ 题解 ll Codeforces ans include 972

A. Simple Palindrome

aeiou,如果这里后面+u则会多出2,+o则会多3,通过分析加相同的字母比加之前存在的不同字母赚
发现同一个太多了,又会增太大,遂平均分配,使增多幅度上升的缓慢

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll gcd(ll x,ll y)
{
	if(y==0)
	return x;
	else
	return gcd(y,x%y);
}
int main()
{
ll t;
cin>>t;
while(t--)
{
	ll n;
	cin>>n;
	ll j=n/5;
	ll u=n%5;
	string f="aeiou";
	for(ll i=0;i<=4;i++)
	{
		ll cnt=j;
		while(cnt>0)
		{
			cnt--;
			cout<<f[i];
		}
		if(i<=u-1)
		{
			cout<<f[i];
		}
	}
	cout<<endl;
}
}

B1,B2.The Strict Teacher

道理都一样,最左或最右直接看相近老师位置。否则,老师就左右夹击,考虑距离除二加细节处理

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll gcd(ll x,ll y)
{
	if(y==0)
	return x;
	else
	return gcd(y,x%y);
}
ll a[200000];
int main()
{
ll t;
cin>>t;
while(t--)
{
	ll n,m,q;
	cin>>n>>m>>q;
	for(ll i=1;i<=m;i++)cin>>a[i];
	sort(a+1,a+1+m);
	while(q--)
	{
		ll x;
		cin>>x;
		if(x>a[m])
		{
			cout<<n-x+x-a[m]<<endl;
		}
		else if(x<a[1])
		{
			cout<<a[1]-x+x-1<<endl;
		}
		else
		{
			ll k=upper_bound(a+1,a+1+m,x)-a;
			cout<<(a[k]-a[k-1])/2<<endl;
		}
	}
}
}

C.Lazy Narek

线性dp,注意之前的先记录下,防止覆盖

//旧数组要自己手动保留,否则会被覆盖
#include<iostream>
#include<string.h>
#include<map>
using namespace std;
typedef long long ll;
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
string f[5000];
ll a[200000];
ll b[10];
ll c[10];
ll d[10];
ll e[10];
int main()
{
	ll t;
	cin >> t;
	while (t--)
	{
		ll n, m;
		cin >> n >> m;
		string k = "narek";
		map<char, ll>q;
		for (ll o = 0; o < 5; o++)
		{
			q[k[o]]++;
		}
		for (ll i = 0; i <= 5; i++)b[i] = 0;
		for (ll i = 0; i <= 5; i++)c[i] = 0;
		for (ll i = 1; i <= n; i++)
		{
			cin >> f[i];
		}
		for (ll i = 1; i <= n; i++)
		{
			for(ll u=0;u<=4;u++)
			{
				e[u]=b[u];
				d[u]=c[u];
			}
			for (ll u = 0; u <= 4; u++)//模拟前面的头
			{
				if (e[u] == 0)
					continue;
				else
				{
					ll ans = 0;
					ll cnt = u;
					ll op = 0;
					for (ll j = 0; j <m; j++)
					{
						if (f[i][j] == k[cnt])
						{
							cnt++;
							if (cnt == 5)
							{
								ans++;
								cnt = 0;
							}
						}
						else
						{
							if (q[f[i][j]] > 0)
							{
								op++;
							}
						}
					}
					if (b[cnt] == 0)
					{
						b[cnt] = 1;
						c[cnt] = d[u] + u + ans * 5 - op - cnt;
					}
					else
					{
						c[cnt] = max(c[cnt], d[u] + u + ans * 5 - op - cnt);
					}
				}
			}
			ll cnt = 0;
			ll ans = 0;
			ll op = 0;
			for (ll j = 0; j < m; j++)
			{
				if (f[i][j] == k[cnt])
				{
					cnt++;
					if (cnt == 5)
					{
						ans++;
						cnt = 0;
					}
				}
				else
				{
					if (q[f[i][j]] > 0)
					{
						op++;
					}
				}
			}
			if (b[cnt] == 0)
			{
				b[cnt] = 1;
				c[cnt] = ans * 5 - op - cnt;
			}
			else
			{
				c[cnt] = max(c[cnt], ans * 5 - op - cnt);
			}
		}
		ll ans = 0;
		for (ll i = 0; i <= 4; i++)
		{
			ans = max(ans, c[i]);
		}
		cout << ans << endl;
	}
}

D.Alter the GCD

参考了别人的代码,出处不在此,但是都源于jly。
一个数组的gcd可能个数为logn
先求前缀gcd和后缀gcd数组
遂先记录前缀gcd相同的最后一个位置
然后考虑枚举右边界,中间的[i,r]的可能个数为也为logn
然后也纪律中间数组gcd相同的最后一个位置,然后枚举这些点就好了,nlognlogn
不得不说,写的很妙,想了两天才理解为何这样做,如何维护中间数组

//维护4个log点
#include<iostream>
#include<string.h>
#include<map>
#include<vector>
#include<set>
#include<unordered_set>
using namespace std;
typedef long long ll;
const ll N = 2e5 + 5;
void fio()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
}
ll gcd(ll x, ll y)
{
	if (y == 0)
		return x;
	else
		return gcd(y, x % y);
}
ll ksm(ll x, ll y)
{
	ll ans = 1;
	while (y)
	{
		if (y & 1)
			ans *= x;
		x *= x;
		y >>= 1;
	}
	return ans;
}
struct s
{
	ll x, y;
};
ll a[N], b[N], prea[N], preb[N], sua[N], sub[N];
s fa[N], fb[N], pa[N], pb[N];
int main()
{
	fio();
	ll t; cin >> t;
	while (t--)
	{
		ll n; cin >> n;
		for (ll i = 1; i <= n; i++)cin >> a[i];
		for (ll i = 1; i <= n; i++)cin >> b[i];
		sua[n + 1] = sub[n + 1] = 0;
		for (ll i = 1; i <= n; i++)//[1,n]
		{
			prea[i] = gcd(prea[i - 1], a[i]);
			preb[i] = gcd(preb[i - 1], b[i]);
			ll z = n - i + 1;
			sua[z] = gcd(sua[z + 1], a[z]);
			sub[z] = gcd(sub[z + 1], b[z]);
		}
		ll cnt1=0, cnt2 = 0;
		for (ll i = 0; i <= n + 1; i++)//维护最后一个没有变化的gcd
		{
			if (i == n + 1 || prea[i] != prea[i + 1])
			{
				cnt1++;
				pa[cnt1] = { prea[i],i+1 };
			}
			if (i == n + 1 || preb[i] != preb[i + 1])
			{
				cnt2++;
				pb[cnt2] = { preb[i],i+1 };
			}
		}
		ll ans = 0, cnt = 0;
		ll l = 0, r1 = 0;//左权值,右位置
		for (ll r = 1; r <= n; r++)//相当于选择什么右边界
		{
			ll k = 0;
			for (ll i = 1; i <= l; i++)//先更新
			{
				ll t = gcd(a[r], fa[i].x); fa[i].x = t;
			}
			for (ll i = 1; i <= l; i++)//后维护
			{
				if (k > 0 && fa[k].x == fa[i].x)
				{
					fa[k].y = fa[i].y;
				}
				else
				{
					k++;
					fa[k] = fa[i];
				}
			}
			l = k; l++; fa[l] = { a[r],r };
			k = 0;
			for (ll i = 1; i <= r1; i++)
			{
				ll t = gcd(b[r], fb[i].x); fb[i].x = t;
			}
			for (ll i = 1; i <= r1; i++)
			{
				if (k > 0 && fb[k].x == fb[i].x)
				{
					fb[k].y = fb[i].y;
				}
				else
				{
					k++;
					fb[k] = fb[i];
				}
			}
			r1 = k; r1++; fb[r1] = { b[r],r };
			ll pa1 = 1, fa1 = 1, pb1 = 1, fb1 = 1;
			ll lst = 0;
			while (1)
			{
				ll u = min(min(pa[pa1].y, pb[pb1].y), min(fa[fa1].y, fb[fb1].y));
				ll t = gcd(pa[pa1].x, gcd(fb[fb1].x, sua[r + 1])) + gcd(pb[pb1].x, gcd(fa[fa1].x, sub[r + 1]));
				if (t > ans)
				{
					ans = t, cnt = u - lst;
				}
				else if (ans == t)
				{
					cnt += u - lst;
				}
				if (u == r)break;
				lst = u;
				if (pa[pa1].y == u)pa1++;
				if (pb[pb1].y == u)pb1++;
				if (fa[fa1].y == u)fa1++;
				if (fb[fb1].y == u)fb1++;
			}
		}
		cout << ans << " " << cnt << endl;
	}
}

标签:cnt,gcd,++,题解,ll,Codeforces,ans,include,972
From: https://www.cnblogs.com/cjcf/p/18456197

相关文章

  • 【题解】2023传智杯全国大学生程序设计竞赛-初赛第一场
    A.字符串拼接直接拼接两个字符串即可,注意的是字符串可能包含空格,因此需要使用getline函数进行输入。#include<bits/stdc++.h>usingnamespacestd;intmain(){strings1,s2;getline(cin,s1);getline(cin,s2);cout<<s1+s2<<endl;return0......
  • SNOI 2020 排列 题解
    https://www.luogu.com.cn/problem/P6795我一直很注重思考过程。这是做题的根本。初看T3,一个比较显然的贪心思路是,向外扩张合并连续段。由此清晰地发现,从1到N,被左边的数切分成若干“剩余”连续段,连续段内部,在右边的排列一定是连续的,右边的答案实际上已经确定。并且这些连......
  • Codeforces Round 977 (Div. 2)(B-C2)
    B:感觉最近几题都用了这种继承的思想。然后就把n方转化为一个递推的问题。我写了一个跟题解不同的做法是取同余也挺巧妙的。#include<bits/stdc++.h>usingnamespacestd;#defineCIconstint&#defineintlonglongconstintmaxn=2e5+10;inta[maxn],vis[maxn],cnt[max......
  • 题解:CF1007D Ants
    题目传送门每只蚂蚁只走一对点肯定是不劣的,由此想到2-sat。限制条件是:若\((a,b)\)和\((c,d)\)两条链相交,则不能同时选。直接建图肯定是爆炸的。用树剖可以将\((a,b)\)这条链划分成\(O(\logn)\)个区间。因为同一条链的区间不交,限制条件变为若两个区间相交,则这两个点不......
  • BUUCTF_MISC题解析(6,8)
    6.乌镇峰会种图把打开的图片放进010editor,拉到最末尾就可以发现flag 8.N种方法解决打开文件是KEY.exe点击打不开,运行不了(exe文件是二进制文件),所以把他拉到010editor打开,data:image/jpg;base64,iVBORw0KGgo......gg==发现是base编码的形式,开头的提示说明是jpg格式的图片,......
  • cf2009 Codeforces Round 971 (Div. 4)
    A.Minimize!签到题。计算\((c-a)+(b-c)\)的最小值,其实值固定的,等于\(b-a\)。inta,b;voidsolve(){cin>>a>>b;cout<<b-a<<endl;}B.Osu!mania签到题。给定一个4k下落式的网格,求#下落顺序。直接数组记录就好了。intn;constintN=500;chars[......
  • codeforces round 974(div.3)E(优先队列实现dijstra算法,devc++的优先队列用greater报
    解题历程:看到两边同时移动,计算最终的相遇时间,我就想到两边同时计算各点到起点的最短距离,就是使用dijstra算法,最后所有节点取两次计算的最大值,再对所有节点取最小值,就是最终答案了,可是这个思路没有考虑有马的情况,思考一番后发现可以多列一个数组记录有马的情况下的行走最短路,然后......
  • P6309 题解
    很经典但是很好的题目。/qiang标签:线段树。数轴上有一些关键点,不同的关键点可能在同一坐标。关键点的坐标均为整数。支持两种操作:删去/添加一些关键点。取一个点。使得它与\([l,r]\)范围内所有关键点的距离最小。求最小距离。\(\text{关键点的坐标数}\le3\times......
  • 深度学习No module named ‘torchvision.transforms.functional_tensor‘问题解决
    问题在进行深度学习训练过程中出现ModuleNotFoundError:Nomodulenamed'torchvision.transforms.functional_tensor'报错,多方查阅资料后得到了解决方案。关于我的环境:CUDA==12.1torch==2.4.1GPU==4090D原先进行深度学习用的CUDA11.3,torch1.2.1,但是在训练时出现nvrtc......
  • Codeforces Round 804 (Div. 2)(C - D)
    CC观察题意,模拟样例,首先\(0\)不能动,因为相邻的\(mex\)会改变,然后\(1\)也是如此,所以我们固定了\(0\)和\(1\),设两个指针\(l\)和\(r\)表示固定的位置,那么此时在他们两个中间的数可以随便移动,假设有\(x\)个空位,那么如果\(2\)在里面,\(2\)的选......