https://codeforces.com/problemset/problem/1312/C
题目大意:
能否对一个数组执行任意次操作,使得其变为目标数组。
对于第i次操作,我们可以放弃,或给数组中任意一个元素加上k^i。
n<=30,k<=100,目标数组元素<=10^16
思路:
注意到题目中,一次操作只能选择一个数。又看到数据范围很小,所以我们可以暴力一点来做。
对于一个可以做到的序列,那序列中每一个数绝对能分解成k^p1+k^p2+k^p3+...的形式.
观察到,对于k=1,无论序列如何,都是可行的。那么除了1之外,最小的是2,所以我们暴力将一个数拆成上面形式的复杂度不超过O(log2 10^16).复杂度显然可以过。
那考虑哪几种情况是无解的:
当序列中的数所拆分出的k的指数有重合,则该序列无解。
于是这个题就这么做完了。对于拆分出来的指数用数组存储次数,一旦>1就可以跳出输出答案了。0跳过即可。
代码实现:
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>
using namespace std;
typedef long long LL;
void solve()
{
map<LL,LL> mp;
LL n,k,x;
cin >> n >> k;
int ff = 1;
while(n --)
{
cin >> x;
for(int i = 0; x > 0 && ff; i ++)
{
int tt = x % k;
if(tt > 1) ff = 0;
if(tt == 1) mp[i] ++;
if(mp[i] > 1) ff = 0;
x /= k;
}
}
if(ff == 0) cout << "NO" << endl;
else cout << "YES" << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(0);
int T = 1;
cin >> T;
while(T --)
{
solve();
}
return 0;
}