POJ(7834)-----分成互质组(openjudge)

来源:互联网 发布:淘宝店铺怎么弄 编辑:程序博客网 时间:2024/06/18 10:14

分成互质组

Description
给定n个正整数,将它们分组,使得每组中任意两个数互质。至少要分成多少个组?

Input
第一行是一个正整数n。1 <= n <= 10。
第二行是n个不大于10000的正整数。

Output
一个正整数,即最少需要的组数。

Sample Input

6
14 20 33 117 143 175

Sample Output

3

Source

2008年第十三届“华罗庚金杯”少年数学邀请赛 决赛第5题

做题地址:OpenJudge-7084:分成互质组 (需要注册)


求解此题,有各种各样的歪门邪道,最常用的有两种:

1:暴力 for for for

2: 套数学方法

作者选择暴力(︿( ̄︶ ̄)︿噜噜噜噜)

而在暴力for下面还有很多细小的优化处理

可以使用求最大连通块的种子法优化:

第一个for寻找未被种子标记的数,使用另一个种子初始化(推荐从1递增)
第二个for寻找与相同种子互质的数,如果全部互质,就加入
最后查看种子的值,得出组数(从1递增的原因之一)


而使用数学方法,则是用了一个性质:

如果a与b互质,c与b互质,则有a*c与b互质

这样如果有两个数互质,就把它们乘起来,继续判断,如果不互质就另开一个。这样确实能避免暴力搜索中的第二个for,但是:

第一行是一个正整数n。1 <= n <= 10。
第二行是n个不大于10000的正整数。

假设遇上最坏的情况,那么乘积的近似值应为10000^10,也就是;

题目极限数据近似值:10000^10=100,000,000,000,000,000,000,000,000,000,000,000,000,00(不要数了,40个0)
long long int极值:2^63-1=922,337,203,685,477,580,7(19位数)
unsigned long long(无符号超长整型)极值:2^64-1=184,467,440,737,095,516,15(19位数)

作者在网上查了一下,最接近10000的10个质数是:

8821 8831 8837 8839 8849 8861 8863 8867 8887 8893

所以,题目极限数据为:

8821*8831*8837*8839*8849*8861*8863*8867*8887*8893
=296,328,592,112,670,000,000,000,000,000,000,000,000,0(40位数)

仍然大于C++中标准数据类型的极值

所以还是暴力好用(︿( ̄︶ ̄)︿噜噜噜噜)


暴力搜索代码

#include<cstdio>#include<algorithm>#include<iostream>using namespace std;struct data{    int s,count;    bool use;}a[15];int n,k;int gcd(int x,int y){    int z = y;      while(x%y!=0)      {          z=x%y;          x=y;          y=z;      }      return z;  }void dfs(int m){    for(int i=1;i<=n;i++)    {        bool flag=1;        if(!a[i].use)        {            for(int j=1;j<=n;j++)                if(a[j].count==m)                    if(gcd(a[j].s,a[i].s)!=1)                    {                        flag=0;                        break;                    }            if(flag)            {                a[i].use=1;                a[i].count=m;            }        }    }}int main(){    scanf("%d",&n);    for(int i=1;i<=n;i++)        scanf("%d",&a[i].s);    for(int i=1;i<=n;i++)    {        if(!a[i].use)        {            a[i].use=1;            a[i].count=++k;            dfs(k);        }    }    printf("%d\n",k);    return 0;}

IN THE END

前面说使用数学方法遇上稍刁钻的数据就会溢出,但是当我交上去后,莫名其妙的

Accepted了!

Accepted了!

Accepted了!

真是不知其尬无以尬人也((⊙o⊙)…)

原创粉丝点击