题解【CF1312C Adding Powers】

\[\texttt{Description} \]

给一个长度为 \(n\) 的数列 \(a\) 和一个全零序列 \(v\) ,以及一个正整数 \(k\)

\(i\) 秒可以选择任意一个位置 \(pos\) ,使得 \(v_{pos}\) 加上 \(k^i\) ,或是什么都不做。

问能否在若干秒后,对于 \(\forall i\) 都有 \(v_i=a_i\)

\[\texttt{Solution} \]

  • 其实可以把问题转化为:第 \(i\) 秒可以选择任意一个位置 \(pos\) ,使得 \(a_{pos}\) 减去 \(k^i\) ,或是什么都不做。问能在否在若干秒后,\(a\) 变成全零序列。
  • 有一个显然的性质:对于任意正整数 \(x\) ,将 \(x\) 化成 \(k\) 进制,设 \(x\)\(k\) 进制表示下的第 \(i\) 位为 \(b_i\) ,则若要将 \(x\) 变为 \(0\) ,则需要减去 \(b_0\)\(k^0\)\(b_1\)\(k^1\)\(b_2\)\(k^2\) ...
  • 注意到,对于每个 \(k^i\) ,至多只能将其使用一次(只能减去一个 \(k^i\) ).
  • 于是就有一个显然的做法了:开个桶 cnt[i] 表示 " 数列 \(a\)\(k\) 进制表示下第 \(i\) 位的和 " ,处理完这个桶后扫一遍,若 \(\exists i\) 满足 \(cnt_i > 1\) ,则答案为 NO ;否则为 YES

\[\texttt{Code} \]

#include
#include

#define RI register int

using namespace std;

const int N=31;

int T;

int n; long long k;

long long a[N];

int cnt[61];

void work()
{
	memset(cnt,0,sizeof(cnt));

	scanf("%d%lld",&n,&k);

	for(RI i=1;i<=n;i++)
		scanf("%lld",&a[i]);

	for(RI i=1;i<=n;i++)
		for(RI j=0;a[i];j++,a[i]/=k)
			cnt[j]+=a[i]%k;

	for(RI i=0;i<=60;i++)
		if(cnt[i]>1)
		{
			puts("NO");
			return;
		}

	puts("YES");
}

int main()
{
	scanf("%d",&T);

	while(T--)    work(); 

	return 0;
}

\[\texttt{Thanks} \ \texttt{for} \ \texttt{watching} \]

你可能感兴趣的:(题解【CF1312C Adding Powers】)