Square-free division (hard version) 题解
题意:给定一个长度为
一个小 Trick:如果两个数乘起来为平方数,可以先将每个数的平方因子除掉,然后这两个数必然相等。于是可以先将每个
首先考虑没有修改的情况怎么做,设
然后考虑有修改操作的情况,我们可以稍微改变一下
注意分解质因数的时候可以先将质数线性筛出来,这样效率更高。
#include<bits/stdc++.h>
using namespace std;
#define re register
const int MAXN = 2e5 + 10,MAXM = 25;
int T,n,k,dp[MAXN][MAXM],a[MAXN],prime[MAXN],cnt,b[MAXN];
int pos[MAXN],last,p[MAXN];
bool is_prime[MAXN];
inline void Get_prime(int n)
{
memset(is_prime,1,sizeof is_prime);
is_prime[1] = 0;
for(re int i = 2;i <= n;i = -~i)
{
if(is_prime[i] == 1) prime[++cnt] = i;
for(re int j = 1;j <= cnt && i * prime[j] <= n;j = -~j)
{
is_prime[i * prime[j]] = 0;
if(i % prime[j] == 0) break;
}
}
}
signed main()
{
cin >> T;
Get_prime(10000);
while(T--)
{
cin >> n >> k;
for(re int i = 1;i <= n;i = -~i) cin >> a[i];
for(re int i = 1;i <= n;i = -~i)
{
for(re int j = 1;j <= cnt;j = -~j)
{
re int val = prime[j];
while(a[i] % (val * val) == 0) a[i] /= (val * val);
if(prime[j] * prime[j] > a[i]) break;
}
b[i] = a[i];
}
sort(b + 1,b + n + 1);
int q = unique(b + 1,b + n + 1) - b - 1;
for(re int i = 1;i <= n;i = -~i) a[i] = lower_bound(b + 1,b + q + 1,a[i]) - b,pos[a[i]] = 0;
for(re int i = 0;i <= k;i = -~i) p[i] = 1,dp[0][i] = 0;
for(re int i = 1;i <= n;i = -~i)
{
re int last = pos[a[i]];
for(re int j = k;j >= 0;j--)
{
if(p[j] > last) continue;
if(j == 0) p[j] = last + 1;
else p[j] = min(last + 1,p[j - 1]);
}
for(re int j = 0;j <= k;j = -~j)
{
dp[i][j] = 1e18;
for(re int k = 0;k <= j;k++) dp[i][j] = min(dp[i][j],dp[p[k] - 1][j - k]);
dp[i][j] = dp[i][j] + 1;
}
pos[a[i]] = i;
}
cout << dp[n][k] << endl;
}
return 0;
}