首页 > 其他 > 详细

Codeforces Round #719 (Div. 3) 题解

时间:2021-05-06 09:30:42      阅读:20      评论:0      收藏:0      [点我收藏+]

https://codeforces.com/contest/1520

在B题上卡了一下,我是SB。

A题

题意:
就问你有没有字母不是连续着出现

思路:
直接判断即可

string s;
int n;
int cnt[26];
 
int main(){
	
	int T;
	cin >> T;
	while(T--)
	{
		memset(cnt, 0, sizeof cnt);
		cin >> n;
		cin >> s;
		bool flag = true;
		for(int i = 0 ; i < n ; i ++)
		{
			if(i && s[i - 1] != s[i])
				if(cnt[s[i] - ‘A‘])
				{
					flag = false;
					break;
				}
			cnt[s[i] - ‘A‘] ++;
		 } 
		if(flag) cout << "YES\n";
		else cout << "NO\n";
	}
	
	return 0;
}

B题

题意:问你从1到n要多少个数是数的每位数字都相等

思路:
直接枚举相同的数字是\(X_i\),然后不断进行\(X_i = X_i * 10 + X_i\)操作,直到数字大于n,统计数目即可。

ll n, k;
 
int main(){
	IOS;
	int T;
	cin >> T;
	while(T--)
	{
		cin >> n;
		ll ans = 0;
		for(ll i = 1 ; i <= 9 ; i ++)
		{
			ll temp = 0;
			while(temp * 10 + i <= n)
			{
				temp = temp * 10 + i;
				ans ++;
			}
		}
		cout << ans <<"\n";
	}
	
	return 0;
}

开始错误的代码
这个写法错在了特判最高位是否可行处

ll n;
vector<int> v;
 
int main(){
	IOS;
	int T;
	cin >> T;
	while(T--)
	{
		cin >> n;
		while(n)
		{
			v.push_back(n % 10);
			n /= 10;
		}
		reverse(v.begin(), v.end());
		int ans = (v.size() - 1) * 9 + v[0] - 1;
		bool flag = true;
		int d = v[0];
		for(auto x : v)  //此处错了
			if(x < d) flag = false;
		if(flag) ans ++;
		cout << ans << "\n";
		v.clear();
	}
	
	return 0;
}

C题

题意:让你将 n * n个数放进 n * n的矩阵里,使得相邻位置的数数值不相邻

思路:
按照顺序,先放奇数,再放偶数,最后判断是否合法即可。

int n;
int g[N][N];
int dx[] = {1, 0, -1, 0};
int dy[] = {0, 1, 0, -1};
 
bool check(int a, int b)
{
	int c = g[a][b];
	for(int i = 0 ; i < 4 ; i ++)
	{
		int x = a + dx[i];
		int y = b + dy[i];
		if(x < 1 || x > n || y < 1 || y > n) continue;
		if(abs(g[x][y] - c) == 1) return false;
	}
	return true;
}
 
int main(){
	IOS;
	int T;
	cin >> T;
	while(T--)
	{
		cin >> n;
		int lim = n * n;
		int l = 1, r = 2;
		for(int i = 1 ; i <= n ; i ++)
			for(int j = 1 ; j <= n ; j ++)
			{
				if(l <= lim) g[i][j] = l, l += 2;
				else g[i][j] = r, r += 2;
			}
		bool flag = true;
		for(int i = 1 ; i <= n ; i ++)
		{
			if(!flag) break;
			for(int j = 1 ; j <= n ; j ++)
			{
				if(!check(i, j)) flag = false;
				break;
			}
		}
		
		if(!flag) cout << "-1\n";
		else
		{
			for(int i = 1 ; i <= n ; i ++)
			{
				for(int j = 1 ; j <= n ; j ++)
					cout << g[i][j] << ‘ ‘;
				cout << ‘\n‘;				
			}
		}
	}
	
	return 0;
}

D题

题意:
给你一个序列,问你有多少序列满足\(i < j\)并且$ a_j - a_i = j - i $。

思路:
将式子变形,变成$ a_j - j = a_i - i $,就非常简单啦

int n;
int a[N];
map<ll, ll> mp;
 
int main(){
	IOS;
	int T;
	cin >> T;
	while(T--)
	{
		cin >> n;
		for(int i = 1 ; i <= n ; i ++)
		{
			cin >> a[i];
			a[i] -= i;
			mp[a[i]] ++;
		}
		
		ll ans = 0;
		for(auto x : mp) ans += x.y * (x.y - 1) / 2;
		cout << ans << "\n";
		mp.clear();
	}
	
	return 0;
}

E题

题意:给你一个字符串,里面有 . 和 * ,每次可以移动一个到.处,问你最少移动多少次可以让所有连续。

思路:
直接线性dp即可,因为你左边怎么凑过来的和右边怎么凑过来的无关,只需要求左边加右边最小即可。

int n;
string s;
pll l[N];
pll r[N];
 
int main(){
	IOS;
	int T;
	cin >> T;
	while(T--)
	{
		cin >> n >> s;
		l[0].y = (s[0] == ‘*‘);
		for(int i = 1 ; i < n ; i ++)
		{
			if(s[i] != ‘*‘)
			{
				l[i].x = l[i - 1].x + l[i - 1].y;
				l[i].y = l[i - 1].y;
			}
			else l[i] = l[i - 1];
			if(s[i] == ‘*‘)
				l[i].y ++;
		}
		
		r[n - 1].y = (s[n - 1] == ‘*‘);
		for(int i = n - 2 ; i >= 0 ; i --)
		{
			if(s[i] != ‘*‘)
			{
				r[i].x = r[i + 1].x + r[i + 1].y;
				r[i].y = r[i + 1].y;				
			}
			else r[i] = r[i + 1];
			if(s[i] == ‘*‘)
				r[i].y ++;
		} 
		
		ll ans = 1e18;
		for(int i = 0 ; i < n ; i ++)
			ans = min(ans, l[i].x + r[i].x);
		cout << ans << "\n";
		for(int i = 0 ; i < n ; i ++)
			l[i].x = l[i].y = r[i].x = r[i].y = 0;
	}
	
	return 0;
}

F1题

题意:
有一个隐藏的数组,只有0和1,让你每次查询一个区间,每次系统会返回区间的和,让你在20次查询内找到数组中的第k个0。

思路:
显然是二分,二分查找即可,详情看如下代码。

int n, t, k;
int sum;
 
int main(){
	IOS;
	cin >> n >> t;
	cin >> k;
	
	int l = 1, r = n;
	while(l < r)
	{
		int mid = l + r >> 1;
		cout << "? " << l << " " << mid << "\n";
		cout.flush();
		cin >> sum;
		if(sum == 0)
		{
			cout << "! " << l + k - 1 << "\n";
			cout.flush();
			return 0;
		}
		if(sum + k <= mid - l + 1)	r = mid;
		else k -= (mid - l + 1 - sum), l = mid + 1;
	}
	cout << "! " << l << "\n";
	cout.flush(); 
	return 0;
}

F1题

题意:
相比F1加入了一条,每次查询到的0,在查询后会变成1,而原来数组中的0该是第几个现在还是第几个。

思路:
需要搞一个东西维护当前查询的0的偏移量,赛中没写出来后面再补。

G题

后面再补

Codeforces Round #719 (Div. 3) 题解

原文:https://www.cnblogs.com/luoyicong/p/14733600.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!