【NOIP2015模拟11.5】JZOJ8月3日提高组T1 Prime

【NOIP2015模拟11.5】JZOJ8月3日提高组T1 Prime

  • 题目
  • 题解
    • 题意
    • 分析
    • Code

题目

在这里插入图片描述
【NOIP2015模拟11.5】JZOJ8月3日提高组T1 Prime_第1张图片

题解

题意

给出 n n n个数,将它们分组
使得每组里任意两个数互质
问最少分成多少组和在满足分成最少组的情况下元素最多的组元素最少是多少

分析

考虑暴力
先预处理出 n n n个数两两之间的互质情况
然后二分答案
对于每个答案暴力判断

Code

#include
#include
#define inf 1073741823
int n,i,j,l,r,mid,ans,ans1,ans2;
int a[20],t[20],c[20][20],s[20][20];
int min(int x,int y)
{
    if (x<y) return x;
    return y;
}
int max(int x,int y)
{
    if (x>y) return x;
    return y;
}
bool judge(int x,int y)
{
    int i;
    for (i=2;i<=x&&i<=y;i++)
        if (x%i==0&&y%i==0) return true;
    return false;
}
void dg(int x,int sum,int mx,int k)
{
    int i,j;
    bool bj;
    if (sum>k) return;
    if (mx>=ans) return;
    if (x>n)
    {
        ans=min(ans,mx);
        return;
    }
    for (i=1;i<=sum;i++)
    {
        bj=true;
        for (j=1;j<=t[i];j++)
        {
            if (c[x][s[i][j]]==true)
            {
                bj=false;
                break;
            }
        }
        if (bj==true)
        {
            t[i]++;
            s[i][t[i]]=x;
            dg(x+1,sum,max(mx,t[i]),k);
            t[i]--;
        }
    }
    t[sum+1]=1;
    s[sum+1][1]=x;
    dg(x+1,sum+1,max(mx,1),k);
    t[sum+1]=0;
}
int main()
{
    freopen("prime.in","r",stdin);
    freopen("prime.out","w",stdout);
    scanf("%d",&n);
    for (i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for (i=1;i<=n;i++)
        for (j=i+1;j<=n;j++)
        {
            if (judge(a[i],a[j])==true)
            {
                c[i][j]=true;
                c[j][i]=true;
            }
        }   
    l=1;
    r=n;
    while (l<=r)
    {
        mid=(l+r)>>1;
        ans=inf;
        dg(1,0,0,mid);
        if (ans==inf) l=mid+1;
        else
        {
            ans1=mid;
            ans2=ans;
            r=mid-1;
        }
    }
    printf("%d %d\n",ans1,ans2);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

你可能感兴趣的:(信息学总结)