CF 980D Perfect Groups(数论)

CF 980D Perfect Groups(数论)

一个数组a的子序列划分仅当这样是合法的:每个划分中的任意两个数乘积是完全平方数。定义a的权值为a的最小子序列划分个数。现在给出一个数组b,问权值为i的b的子串个数。

这题意真不是人类智慧能轻易描述的。据说此题在比赛场上读题30min,做题5min,做完还WA。果然是坑题。

如果有两个数a和b,a和b的乘积是完全平方数,那么如果a有因子x^2,那么x^2就可以去掉,使a变成a/x^2,结论依然成立。因此我们把所有数的质因子次数mod2,可以发现结论仍然不变。

因此,在一个划分内的数必须完全相同或者有数为零(涉及乘除法一定要考虑零啊啊啊)。n^2dp即可。

#include <cstdio> 
#include <algorithm>
using namespace std;

const int maxn=5005;
int n, a[maxn], b[maxn], cnt[maxn];  //cnt[i]储存i有几个 
int k, ans[maxn], id0;

int deal(int x){
    int flag;
    if (x<0) x=-x, flag=-1; else flag=1;
    for (int i=2; i*i<=x; ++i) 
        while (x%(i*i)==0) x/=i*i;
    return x*flag;
}

int main(){
    scanf("%d", &n); int t; id0=-1;
    for (int i=1; i<=n; ++i){
        scanf("%d", &t), a[i]=b[i]=deal(t);
        if (!a[i]) id0=0;
    }
    sort(b+1, b+1+n); 
    if (!id0) id0=lower_bound(b+1, b+1+n, 0)-b;
    for (int i=1; i<=n; ++i)
        a[i]=lower_bound(b+1, b+1+n, a[i])-b;
    for (int i=1; i<=n; ++i){
        for (int j=1; j<=n; ++j) cnt[j]=0; k=0;  //k:[i,j]不同元素的数目 
        for (int j=i; j<=n; ++j){
            if (a[j]==id0){
                if (!k) ++ans[1]; else ++ans[k];
                continue;   
            }
            if (!cnt[a[j]]) ++k;
            ++cnt[a[j]]; ++ans[k];
        }
    }
    for (int i=1; i<=n; ++i) printf("%d ", ans[i]);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/MyNameIsPc/p/9053087.html