题目链接:https://codeforc.es/contest/1696/problem/C

大意:

给定一个长度为  的数组  、一个长度为  的数组 和一个数字 m,现在对数组 a 进行以下操作:

  • 选择数组  中一个 m 的倍数  替换成 m 个 ai*m
  • 选择数组  中  个相同的数字 替换成     (这个最开始理解错了,理解成了相同的数,而非m个)

请问能否把数组  变成数组 
数据范围:

思路:这个题最开始理解错了,所以没看出什么技巧来。在网上看了题解的大意,我看出了1操作可以通过2操作来进行逆操作,所以我们只需要把数组a和数组b全部用操作1来  拆分成子结构,然后合并成最简的子结构,即数组存储元素为num和连续个num的数量。然后再去对比数组a的结构和数组b的结构。

解决方法:有了这个思路就很好去解决了,可以用vector存储数组a和数组b拆分的子结构,一边拆分一边进行合并。合并过程可以使用vector里的erase方法。

code:


#include<bits/stdc++.h>
using namespace std;
#define ll long long
struct number{
	ll num;
	ll cnt;
};
vector<number> va;
vector<number> vb;
int main()
{
	ll t;
	scanf("%lld",&t);
	while(t--)
	{
		ll n,m,x,k;
		va.clear(); vb.clear();
		scanf("%lld%lld",&n,&m);
		for(ll i=1;i<=n;i++)
		{
			scanf("%lld",&x);
			if(i==1||va[va.size()-1].num!=x)
			{
				va.push_back({x,1});
			}else
			{
				va[va.size()-1].cnt++;
			}
		}
		scanf("%lld",&k);
		for(ll i=1;i<=k;i++)
		{
			scanf("%lld",&x);
			if(i==1||vb[vb.size()-1].num!=x)
			{
				vb.push_back({x,1});
			}else
			{
				vb[vb.size()-1].cnt++;
			}
		}
		for(ll i =0;i<va.size();i++)
		{
			while(va[i].num % m == 0)
			{
				va[i].num = va[i].num/m;
				va[i].cnt = va[i].cnt*m;
			}
			if(i!=0 && va[i].num == va[i-1].num)
			{
				va[i-1].cnt += va[i].cnt;
				va.erase(va.begin()+i);
				i--;
			}
		}
		for(ll i =0;i<vb.size();i++)
		{
			while(vb[i].num % m == 0)
			{
				vb[i].num = vb[i].num/m;
				vb[i].cnt = vb[i].cnt*m;
			}
			if(i!=0 && vb[i].num == vb[i-1].num)
			{
				vb[i-1].cnt += vb[i].cnt;
				vb.erase(vb.begin()+i);
				i--;
			}
		}
		
		//对比
		if(va.size()!=vb.size())
			printf("NO\n");
		else
		{	
			ll i=0;
		 	for(;i<va.size();i++)
		 	{
		 		if(va[i].num!=vb[i].num||va[i].cnt!=vb[i].cnt)
					break;
			}
			if(i==va.size())
				printf("YES\n");
			else
				printf("NO\n");
		} 
	}
 }