CodeForces 124C【连通块】

思路:

a素数->b合数

c素数->b合数

a,c属于一类

so,预处理相同的,并且计数。1000怎么搞都无压力;
我这里也预处理了字母个数,从集合大的枚举下来,每次拿字母个数最多的去匹配。

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;

const int N=1e3+10;

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

pair<int,int>sum[1010];
int ssum[30];

char s[N],ans[N];
bool vis[N];
int n;
vector<int>prime;
vector<int>num[200];


void init()
{
    for(int i=1; i<=1000; i++)
        if(isprime(i)) prime.push_back(i);
}

int pre[N];
int Find(int x)
{
    int r=x;
    while(pre[r]!=r)
        r=pre[r];
    int i=x,j;
    while(pre[i]!=r)
    {
        j=pre[i];
        pre[i]=r;
        i=j;
    }
    return r;
}

pair<int,int>xs[1010];
vector<int>pp[1010];

int main()
{
    //预处理素数
    init();

    scanf("%s",s+1);
    n=strlen(s+1);

    //求和
    for(int i=1; i<=n; i++)
    {
        int x=s[i]-'a';
        ssum[x]++;
    }
    for(int i=0; i<26; i++)
    {
        sum[i].first=ssum[i];
        sum[i].second=i;
    }

    //分块。
    int sz=prime.size();
    int ssz=sz;
    for(int i=0; i<sz; i++)
    {
        if(prime[i]>n)
        {
            ssz=i;
            break;
        }
        for(int k=1; k<=n; k++)
        {
            if(k*prime[i]>n) break;
            num[i].push_back(k*prime[i]);
        }
    }
    for(int i=1; i<=n; i++)
        pre[i]=i;
    for(int i=0; i<ssz; i++)
    {
        int u=prime[i];
        int sss=num[i].size();
        for(int k=0; k<sss; k++)
        {
            int v=num[i][k];
            int uu=Find(u);
            int vv=Find(v);
            if(uu!=vv)
                pre[uu]=vv;
        }
    }
    //建立 集合个数 和 集合元素
    for(int i=1;i<=n;i++)
        xs[i].first=0;
    for(int i=1; i<=n; i++)
    {
        int x=Find(i);
        xs[x].first++;
        xs[x].second=x;
        pp[x].push_back(i);
    }

    //从大到小
    sort(xs+1,xs+n+1);
    sort(sum,sum+26);
//    for(int i=n;i>=1;i--)
//    {
//        printf("%d %d\n",xs[i].first,xs[i].second);
//    }
//    for(int j=25;j>=23;j--)
//    {
//        printf("%d\n",sum[j].first);
//    }
    for(int i=n; i>=1; i--)
    {
        int sz=xs[i].first;     //集合个数
        int x=xs[i].second;     //集合老大
        if(pp[x].size()==0) break;
        bool flag=false;
        int j=25;
        if(sum[j].first>=sz)
        {
            for(int k=0; k<sz; k++)
                ans[pp[x][k]-1]=sum[j].second+'a';
            sum[j].first-=sz;
        }
        else
            flag=true;
        sort(sum,sum+26);
        if(flag)
        {
            puts("NO");
            return 0;
        }
    }
    ans[n]='\0';
    puts("YES");
    printf("%s\n",ans);
    return 0;
}


posted @ 2017-03-21 22:54  see_you_later  阅读(217)  评论(0编辑  收藏  举报