思维训练2

题目描述1

Problem - A - Codeforces

题目分析

通过题目发现a[1] = d[1],

a[i] = d[i] + a[i - 1]

由于所有的数都为正数,所以只要出现a[i - 1] - d[i] >= 0这种情况a[i]就可以取为绝对值,也就是说a[i]会有一正一负两种情况,当然,如果在这个a[i - 1] - d[i] >= 0条件我们要保证d[i]是不为0的不然正负都是只有一种情况

#include
using namespace std;
const int N = 2e5 + 10;
int d[N], a[N];
void solve()
{
	int n;
	memset(d, 0, sizeof d);
	memset(a, 0, sizeof a);
	cin >> n;
	for(int i = 1; i <= n; i ++)cin >> d[i];
	a[1] = d[1];
	for(int i = 2; i <= n; i ++)
	{
		a[i] = d[i] + a[i - 1];
		if(d[i] && a[i - 1] - d[i] >= 0)
		{
			cout << - 1 << '\n';
			return;
		}
	}
	for(int i = 1; i <= n; i ++)cout << a[i] << ' ';
	cout << '\n';
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int t;
	cin >> t;
	while(t --)
	{
		solve();
	}
	return 0;
}

题目描述2 

Problem - B - Codeforces

思维训练2_第1张图片

题目分析

我们最终的目的是为了升序排序,且其操作为反转操作,故我们从数组两边使用双指针,遇到01需要进行反转的就停下做出一次记录(此处使用vector)即可,注意输出时从小到大即可,所以需要排序

#include
using  namespace std;
const int N = 2e5 + 10;
void solve()
{
	char a[N];
	int n, flag = 0;
	cin >> n;
	for(int i = 1; i <= n; i ++)
	{
		cin >> a[i];
	}
	for(int i = 2; i <= n; i ++)
	{
		if(a[i - 1] > a[i])flag = 1;
	}
	if(!flag)
	{
		cout << 0 << '\n';
	}
	else
	{
		vector v;
		int l = 1, r = n;
		while(l < r)
		{
			while(l < r && a[l] == '0')l ++;
			while(l < r && a[r] == '1')r --;
			if(l < r)
			{
				v.push_back(l);
				v.push_back(r);
				l ++;
				r --;
			}
		}
		sort(v.begin(), v.end());
		cout << 1 << '\n' << v.size() << ' ';
		for(auto i : v)
		{
			cout << i << ' ';
		}
		cout << '\n';
	}
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int t;
	cin >> t;
	while(t --)
	{
		solve();
	}
	return 0;
}

题目描述3

Problem - C - Codeforces

思维训练2_第2张图片

题目分析

将10拆解成2和5,因为只有2 * 5可以拆解成10,如果少2就乘2或者少5就乘5,如果还可以继续就乘10,由于此时末尾都为0,故还可以乘到小于m的倍数

思维训练2_第3张图片 

#include
using namespace std;
typedef long long ll;
void solve()
{
	ll n, m;
	cin >> n >> m;
	ll k = 1;
	ll t = n;
	ll c2 = 0, c5 = 0;
	while(t % 2 == 0)t /= 2, c2 ++;
	while(t % 5 == 0)t /= 5, c5 ++;
	while(c2 < c5 && k * 2 <= m)k *= 2, c2 ++;
	while(c5 < c2 && k * 5 <= m)k *= 5, c5 ++;
	while(k * 10 <= m)k *= 10;
	cout << n * k * (m / k) << '\n';
}
int main()
{
	int t;
	cin >> t;
	while(t --)
	{
		solve();
	}
	return 0;
}

题目描述4

Problem - D - Codeforces

题目分析 

对于此题主要是数的配对,我们将数都存入map将数组排序,从大到小来看每一个数,如果其数/x在map中还存在说明这两个数字可以配对,将这个数字以及可以和这个数配对的数字删除,如果说没有可以/x的数说明不能配对此时就需要添加数字用ans记录添加的个数

#include
using namespace std;
typedef long long ll;
const int N = 2e5 + 10;
void solve()
{
	int ans = 0;
	int n, x;
	map mp;
	int a[N];
	cin >> n >> x;
	for(int i = 1; i <= n; i ++)
	{
		cin >> a[i];
		mp[a[i]] ++;
	}
	sort(a + 1, a + 1 + n);
	for(int i = n; i >= 1; i --)
	{
		if(mp[a[i]])
		{
			if(a[i] % x == 0)
			{
				if(mp[a[i] / x] == 0)
				{
					ans ++;
					mp[a[i]] --;
				}
				else
				{
					mp[a[i]] --;
					mp[a[i] / x] --;
				}
			}
			else
			{
				mp[a[i]] --;
				ans ++;
			}
		}
	}
	cout << ans << '\n';
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int t;
	cin >> t;
	while(t --)
	{
		solve();
	}
	return 0;
}

题目描述5

Problem - E - Codeforces

思维训练2_第4张图片

题目分析

我们可以将每一列存在vector中进行计算,使用下方的区间模型将答案加入ans

思维训练2_第5张图片

思维训练2_第6张图片

#include
using namespace std;
typedef long long ll;
vector> v;
void solve()
{
	int n, m, x;
	ll ans = 0;
	cin >> n >> m;
	v.clear();
	v.resize(m + 1);
	for(int i = 1; i <= n; i ++)
	{
		for(int j = 1; j <= m; j ++)
		{
			cin >> x;
			v[j].push_back(x);
		}
	}
	for(int i = 1; i <= m; i ++)
	{
		sort(v[i].begin(), v[i].end());
		for(int j = 1; j < n; j ++)
		{
			ans += 1ll * (v[i][j] - v[i][j - 1]) * j * (n - j);
		}
	}
	cout << ans << '\n';
}
int main()
{
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	int t;
	cin >> t;
	while(t --)
	{
		solve();
	} 
	return 0;
}

你可能感兴趣的:(算法)