Codeforces Round #480 (Div. 2) D. Perfect Groups(数论/xjblg)

今天vp了一下昨天的这场比赛,结束后看着rank,还好没打,
这场完全就是题意场啊,做题10mins,读题1h……..

这个D题题意是真的有点魔性:

首先第一段描述的ansans是指给你一个array,使得你能将他分成numnum个集合,使得集合中任意两个书之积为完全平方数,且numnum是满足条件的最小集合数。

第二三段讲的是给你另一个array,长度为n,你的第i行要输出满足第一段query且ans==ians==i的连续子串个数。

我们来解释一下样例:

example #1:

2 
5 5

output: 

3 0 

第一个要输出的是ans==1的子串个数,满足的子串很明显有{5},{5},{5,5} 

他们都不可再分故ans=1

第二个要输出的是ans==2,只有一个元素的集合很明显不满足,对这组数据而言,”可能“满足的只有{5,5}这个子串,但是这个子串的最小分割集合数为1,故i=2时应输出0.

解决的方法比较暴力,我们可以做一个简单的小推论,满足相乘为完全平方数的两个数他们的相同的因子的个数之和必定为偶数,那么我们就可以在sqrt(num)的时间里处理出最后实际需要判定的num

之后存一个对于num位置的前缀,便可以在n∗n的时间里处理所有子串。

这里还有一个地方需要注意,题目中给你的ai它可能是负数啊啊啊啊啊啊

or you will get wa18 (╯‵□′)╯︵┻━┻

#include<cstdio>
#include<iomanip>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<set>
#include<queue>
#include<limits.h>
#include<string.h>
#include<map>
#include<list>
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

#define inf int(0x3f3f3f3f)
#define mod int(1e9+7)
#define eps double(1e-6)
#define pi acos(-1.0)
#define lson  root << 1
#define rson  root << 1 | 1

int n;

int a[5005];

int s[5005];

int pre[5005];

map<int, int> mp;

int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    cin>>n;
    mp.clear();
    for(int i=1; i<=n; i++)
    {
        cin>>a[i];
        int symb=1;
        for(int j=2; j*j<=abs(a[i]); j++)
        {
            while(a[i]%(j*j)==0)
            {
                a[i]/=j*j;
            }
        }
    }
    for(int i=1; i<=n; i++)
    {
        pre[i]=mp[a[i]];
        mp[a[i]]=i;
    }
    memset(s,0,sizeof(s));
    for(int i=1; i<=n; i++)
    {
        int cur=0;
        for(int j=i; j<=n; j++)
        {
            if(a[j]&&pre[j]<i)
                cur++;
            s[max(1,cur)]++;
        }
    }
    for(int i=1; i<=n; i++)
        cout<<s[i]<<" ";
    cout<<"\n";
}