Codeforces #480 Tutorial

Problem A,B,C:

简单的模拟,注意A中p mod q时对q=0特殊处理(注意范围)


Problem D:

Brief Intro:

给定长度为N的数组A,将A中所有连续子序列分成最少的组,使得每组任意一对数的积均为完全平方数

求最终分成组数为K的子序列个数,K属于[1,N]

Algorithm:

能推出的性质:若P,Q两数积为完全平方数,则任意一个质因子的次幂的奇偶性必然相同

那么想判断P,Q是否满足条件,只要保留每个质因子的次幂为0或1,再判断P,Q是否相同即可

下面只要考虑如何O(N^2)地判断

为了能O(1)判断新加入的数是否已经出现过,需要预处理出每一个数的上一个“自己”出现的位置

由于数的范围过广,使用map记录一个数在检索到k时最后的位置

Code:

#include <bits/stdc++.h>

using namespace std;

const int MAXN=5000+10;
int n,dat[MAXN],res[MAXN],pre[MAXN];

vector<int> prime;
map<int,int> mp;

bool isprime(int x)
{
    int up_limit=sqrt(x);
    for(int i=2;i<=up_limit;i++)
        if(x%i==0) return false;
    return true;
}

void init()
{
    int up_limit=sqrt(1e8+10);
    for(int i=2;i<=up_limit;i++)
        if(isprime(i)) prime.push_back(i);
}

int trans(int x)
{
    int up_limit=sqrt(abs(x)),ret=x;
    for(int i=0;i<prime.size();i++)
    {
        if(prime[i]>up_limit || ret==1 || ret==-1) break;
        
        int t=ret,cnt=0;
        while(t%prime[i]==0) t/=prime[i],cnt++;
        if(cnt%2==1) ret=t*prime[i];
        else ret=t;
    }
    return ret;
}

int main()
{
    cin >> n;
    for(int i=1;i<=n;i++)
        cin >> dat[i];
        
    init();
    
    for(int i=1;i<=n;i++) //质因数分解
        dat[i]=trans(dat[i]);
        
    for(int i=1;i<=n;i++)  //预处理pre
        if(mp.count(dat[i]))
        {
            pre[i]=mp[dat[i]];
            mp[dat[i]]=i;
        }
        else
        {
            pre[i]=-1;
            mp[dat[i]]=i;
        }
    
    for(int i=1;i<=n;i++)
    {
        bool f=true;int cnt=0;
        for(int j=i;j<=n;j++)
        {
            if(dat[j]) f=false;
            if(pre[j]<i && dat[j]) cnt++,mp[dat[j]]=true; //O(1)判断
            if(!f) res[cnt]++;
            else res[1]++; 
        }
    }
    
    for(int i=1;i<=n;i++) cout << res[i] << " ";
    return 0;
}

Review:

1、特解:0

在看到数据范围后,总要考虑特解。

除非一段全部为0,否则忽略当前遇到的0

2、积为完全平方数的性质:

我当时只想到了传导性,反而忽略了每个质因子次幂奇偶性相同这一性质

只考虑奇偶性   到    转化后判断相等的方法值得借鉴

3、求解一串数中不同数的个数的预处理:

求出每一个数前一次出现的位置     常用的预处理方式

猜你喜欢

转载自www.cnblogs.com/newera/p/9048713.html