UVALive 6198 A Terribly Grimm Problem

题目大意是


给出L,H      10^10范围

为[L, H]这个连续的整数区间寻找一个序列。

序列的长度要跟[L, H]一样

然后序列中的数都是素数,并且互不相同

并且序列中第i个数 要求是L + i -1的一个素因子 

最后要求序列的字典序最小


然后可以看到L,H很大

但是我们需要注意的是,这个序列长度肯定不会很大

太大了肯定满足不了题目的要求。


所以这个整数区间的数我们可以一个一个的,先把每个数都素因子分解了,放起来。

然后就发现。 这不就是二分图匹配么。

但是题目求的是字典序最小。

所以我们就对每个数。

对其所有的素因子,尝试改变匹配,然后寻找增广路。

如果能找到。就固定这条边


 

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cstdlib>

#include <string>

#include <cmath>

#include <vector>

#include <map>

#include <set>

#include <algorithm>

#define MAXN 111111

#define N 505

using namespace std;

bool tag[MAXN];

int p[MAXN];

int cnt;

int mark[5555], used[5555];

int cx[N], cy[5555];

vector<int>g[N];

int ans[N];

int m, up;

long long l, r;

long long a[MAXN];

set<long long>s;

map<long long, int> id;

void getprime()

{

    cnt = 0;

    tag[1] = 1;

    for(int i = 2; i < 100000; i++)

    {

        if(!tag[i]) p[cnt++] = i;

        for(int j = 0; j < cnt && p[j] * i < 100000; j++)

        {

            tag[i * p[j]] = 1;

            if(i % p[j] == 0) break;

        }

    }

}

void get(long long x)

{

    for(int i = 0; i < cnt && x >= (long long)p[i] * (long long)p[i]; i++)

        if(x % p[i] == 0)

        {

            s.insert(p[i]);

            while(x % p[i] == 0) x /= p[i];

        }

    if(x != 1)

        s.insert(x);

}

void get2(long long x)

{

    long long tx = x;

    for(int i = 0; i < cnt && x >= (long long)p[i] * (long long)p[i]; i++)

        if(x % p[i] == 0)

        {

            long long tmp = (long long)p[i];

            while(x % tmp == 0) x /= tmp;

            g[tx - l + 1].push_back(id[tmp]);

        }

    if(x != 1)

        g[tx - l + 1].push_back(id[x]);

}

int path(int u)

{

    int sz = g[u].size();

    for(int i = 0; i < sz; i++)

    {

        int v = g[u][i];



        if(!mark[v] && !used[v])

        {

            mark[v] = 1;

            if(cy[v] == -1 || path(cy[v]))

            {

                cx[u] = v;

                cy[v] = u;

                return 1;

            }

        }

    }

    return 0;

}



bool ok(int t)

{

    memset(cy, -1, sizeof(cy));

    for(int i = t + 1; i <= up; i++)

    {

        memset(mark, 0, sizeof(mark));

        if(!path(i)) return false;

    }

    return true;

}

void fix()

{

    for(int i = 1; i <= up; i++)

    {

        int sz = g[i].size();

        for(int j = 0; j < sz; j++)

        {

            int v = g[i][j];

            if(used[v]) continue;

            cx[i] = v;

            used[v] = 1;

            if(!ok(i)) used[v] = 0;

            else break;

        }

        used[cx[i]] = 1;

    }

}

void out(long long a )

{

    if(a >= 10) out(a / 10);

    putchar('0' + a % 10);

}

int main()

{

    getprime();



    while(scanf("%lld%lld", &l, &r) != EOF)

    {

        if(l == 0 && r == 0) break;

        s.clear();

        id.clear();

        up = r - l + 1;

        for(int i = 1; i <= up; i++) g[i].clear();

        memset(ans, -1, sizeof(ans));

        memset(used, 0, sizeof(used));

        m = 0;

        for(long long i = l; i <= r; i++)

            get(i);

        for(set<long long>::iterator it = s.begin(); it != s.end(); it++)

        {

            a[m++] = *it;

            id[a[m - 1]] = m;

        }

        for(long long i = l; i <= r; i++)

            get2(i);

        fix();

        for(int i = 1; i < up; i++)

        {

            //printf("%lld ", a[cx[i] - 1]);

            out(a[cx[i] - 1]);

            putchar(' ');

        }

        out(a[cx[up] - 1]);

        putchar('\n');

        //printf("%lld\n", a[cx[up] - 1]);

    }

    return 0;

}


 

 

你可能感兴趣的:(live)