51nod 1280 Prefix suffix set (discretization, hash, prime table)

Posted by DigitalExpl0it on Mon, 06 Jan 2020 01:00:16 +0100

Title Link

https://www.51nod.com/onlineJudge/submitDetail.html#!judgeId=627203

meaning of the title

An array contains n positive integers, some of which are duplicates. A Prefix suffix set is a subscript pair (P,S) that satisfies the following conditions: 0 < = P, s < n the value of array element A[0..P] also appears in the value of A[S..N - 1], and the value of A[S..N - 1] also appears in A[0..P]. In other words, the prefix set A[0..P] and the suffix set A[S..N - 1] contain exactly the same values. Find the number of such sets of prefixes and suffixes.

For example: 3 5 7 3 3 5, a total of 14 sets meet the conditions: (1, 4), (1, 3), (2, 2), (2, 1), (2, 0), (3, 2), (3, 1), (3, 0), (4, 2), (4, 1), (4, 0), (5, 2), (5, 1), (5, 0)

Title Solution

Each prefix maps a value, and each suffix maps a value. According to the mapping value, we can judge whether the prefix and suffix contain exactly the same value.

According to the contribution of each value and only once, we can discretize these N values into several prime numbers.
Then, from the unique decomposition theorem of prime numbers, we can see that the values obtained by multiplying prime numbers are one-to-one correspondence.

And since N may have a maximum of 50000 prime numbers, all of them can't be multiplied by long long. Use unsigned long long to overflow naturally, which is equivalent to module 2 ^ 64.

AC code

#include <bits/stdc++.h>
using namespace std;
typedef unsigned long long ull;
const int maxn=5e4+7;

int prime[maxn]={2,3,5,7,11,13,17};//7

void getPrime()
{
    int i=7,n=19;
    while(i<maxn)
    {
        int tmp=(int)sqrt(n+0.5),j;
        for(j=0;prime[j]<=tmp;j++)
        {
            if(n%prime[j]==0) break;
        }
        if(prime[j]>tmp)
        {
            prime[i++]=n;
        }
        n+=2;
    }
}

vector<int> V;
int getid(int x)
{
    return lower_bound(V.begin(),V.end(),x)-V.begin()+1;
}
int a[maxn];
map<ull,int> mp;
bool vis[maxn];
int main()
{
    int n;
    getPrime();
    while(~scanf("%d",&n))
    {
        V.clear();
        for(int i=0;i<n;i++)
        {
            int x;
            scanf("%d",&x);
            a[i]=x;
            V.push_back(x);
        }
        sort(V.begin(),V.end());
        V.erase(unique(V.begin(),V.end()),V.end());
        mp.clear();
        memset(vis,false,sizeof(vis));

        ull now=1;
        for(int i=0;i<n;i++)
        {
            int id=getid(a[i]);


            if(!vis[id]) now=now*(ull)prime[id];
            vis[id]=true;
            //cout<<"now1="<<now<<endl;
            mp[now]++;
        }

        now=1;
        long long ans=0;
        memset(vis,false,sizeof(vis));
        for(int i=n-1;i>=0;i--)
        {
            int id=getid(a[i]);
            if(!vis[id])   now=now*(ull)prime[id];
            vis[id]=true;
            //cout<<"now2="<<now<<endl;
            if(!mp[now]) continue;
            ans+=mp[now];
        }
        printf("%lld\n",ans);
    }
    return 0;
}