小学奥数 7834 分成互质组
1221:分成互质组
总时间限制:
1000ms
内存限制:
65536kB
描述
给定n个正整数,将它们分组,使得每组中任意两个数互质。至少要分成多少个组?
输入
第一行是一个正整数n。1 <= n <= 10。
第二行是n个不大于10000的正整数。
输出
一个正整数,即最少需要的组数。
样例输入
6 14 20 33 117 143 175
样例输出
3
来源
2008年第十三届“华罗庚金杯”少年数学邀请赛 决赛第5题
C++参考代码一:
/*
1221:分成互质组
http://ybt.ssoier.cn:8088/problem_show.php?pid=1221
*/
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#define N 20
using namespace std;
int n;
int a[N];
int cnt=99999;
long long vis[N];
long long gcd(long long a,long long b)
{
if(b==0)
return a;
return
gcd(b,a%b);
}
void dfs(int k,int step)
{
if(step==n+1)
{
if(k<cnt)
cnt=k;
return;
}
for(int i=1;i<=k;i++)
if(gcd(vis[i],a[step])==1)
{
vis[i]*=a[step];
dfs(k,step+1);
vis[i]/=a[step];
}
vis[k+1]*=a[step];
dfs(k+1,step+1);
vis[k+1]/=a[step];
}
int main( void )
{
int temp;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
vis[i]=1;
}
sort(a+1,a+1+n);
dfs(1,1);
cout<<cnt<<endl;
return 0;
}
C++参考代码二:
#include<iostream> #include<cstring> #include<cstdio> #include<queue> #include<stack> #include<algorithm> #include<vector> #include<map> #include<vector> using namespace std; vector<int> v[10000]; int cnt=0; int pd(int x,int y){ int minn=min(x,y); for(int i=minn;i>=2;i--){ if(x%i==0&&y%i==0) return 0; } return 1; } int main(){ int n; cin>>n; int num; cin>>num; v[cnt++].push_back(num); for(int i=1;i<n;i++){ cin>>num; int flag=0; for(int j=0;j<cnt;j++){ int k; for(k=0;k<v[j].size();k++){ if(pd(v[j][k],num)==0){ break; } } if(k==v[j].size()){ v[j].push_back(num); flag=1; break; } } if(flag==0){ v[cnt++].push_back(num); } } cout<<cnt<<endl; /*for(int i=0;i<cnt;i++){ for(int j=0;j<v[i].size();j++) cout<<v[i][j]<<" "; cout<<endl; }*/ return 0; }
C++参考代码三:
#include<iostream>
using namespace std;
int n,ans=1e9+1;
bool flag;
int a[10010],b[10010];//a[]保存数
int panduan(int a,int b)//递归法判断互质
{
if(b==0)return a;
return panduan(b,a%b);
}
void dfs(int x,int y)//搜到了第x个数,现在有y个集合
{
if(x==n+1)//搜索完成,取最小值,退出
{
ans=min(ans,y);
return;
}
for(int i=1;i<=y;i++)//组数
{
flag=true;
for(int j=1;j<x;j++)//不能加‘=’,因为如果加了‘=’,一个数就可以进这重循环,即x=1时,不可能自己比自己吧。
{
if(b[j]==i)
{
if(panduan(a[x],a[j])!=1)//如果不为互质数
{
flag=false;//就没必要比,再继续加下去了,
break;//跳出
}
}
}
if(flag)//如果前边加的数字都为互质数,就再加数,继续判断
{
b[x]=i;//保存组数
dfs(x+1,y);//加数字,但不加组
b[x]=0;//回溯
}
}
b[x]=y+1;//集合数加1
dfs(x+1,y+1);//进行下一次查找
b[x]=0; //回溯
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
dfs(1,1);//从第一个(数,组)开始
cout<<ans<<endl;
return 0;
}
C++参考代码四:
/*
小学奥数 7834:分成互质组
http://noi.openjudge.cn/math/7834/
*/
#include<stdio.h>
#define N 15
int a[N]; //存数数组
int vis[N]; //访问数组
int cnt; //分组数
int gcd(int a,int b)
{
return a%b==0 ? b : gcd(b,a%b);
}
int main()
{
int i,j,n;
scanf("%d",&n);
for(i=0;i<n;i++)
scanf("%d",&a[i]);
for(i=0;i<n;i++)
{
if(!vis[i])
{
vis[i]=1;
cnt++;
for(j=i+1;j<n;j++)
{
if(!vis[j] && gcd(a[i],a[j])==1) //未访问且互质,添加进组
{
a[i]*=a[j]; //2,3互质,再判断就需要和6互质
vis[j]=1;
}
}
}
}
printf("%d\n",cnt);
return 0;
}
C++参考代码五:
#include<cstdio>
#include<algorithm>
#include<string.h>
using namespace std;
int n,line[15],edge[15][15],color[15],visit[15][15],ans=20,cnt;
int DFS(int x)
{
if(x>n){
if(ans>cnt)ans=cnt;
return 0;
}
memset(visit[x],1,sizeof(visit[x]));
for(int i=1;i<x;++i)
{
if(edge[i][x])continue;
visit[x][color[i]]=0;
}
for(int i=1;i<=cnt;++i)
{
if(visit[x][i]){
color[x]=i;
DFS(x+1);
}
}
if(cnt<ans){
++cnt;
color[x]=cnt;
DFS(x+1);
--cnt;
}
return 0;
}
int gcd(int a,int b)
{
return a%b==0 ? b:gcd(b,a%b);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
{
scanf("%d",&line[i]);
}
for(int i=1;i<=n;++i)
{
for(int j=i+1;j<=n;++j)
{
if(gcd(line[i],line[j])==1)
{
edge[i][j]=edge[j][i]=1;
}
}
}
color[1]=1;
++cnt;
DFS(2);
printf("%d",ans);
return 0;
}
python3代码:
"""
小学奥数 7834 分成互质组03
http://noi.openjudge.cn/math/7834/
"""
import sys
import math
a=[]
vis=[]
N = 15
"""
for i in range ( N +1) :
a.append(0)
"""
for i in range ( N +1) :
vis.append(0)
cnt=0
def gcd( a,b):
if a%b==0:
return b
else:
return gcd(b,a%b)
n=int(input())
a = list(map(int,input().split()))
#print(a)
"""
for i in range(n):
a[i]=int(input())
"""
for i in range(n):
if vis[i]==0:
vis[i]=1
cnt+=1
for j in range(i+1,n):
if vis[j]==0 and gcd(a[i],a[j])==1:
a[i]*=a[j]
vis[j]=1
print(cnt)
电子学会 青少年软件编程等级考试 C语言 5 级
【OpenJudge NOI】题解目录
电子学会青少年编程等级考试
中国电子学会考评中心
软件编程(C语言)