Factors |
||
| Accepted : 9 | Submit : 65 | |
| Time Limit : 1000 MS | Memory Limit : 65536 KB | |
题目描述从前有个叫天天的熊孩子,他非常喜欢数字1。为什么呢?因为一生二,二生三,三生万物,由此熊孩子认为1是万物之始。现在天天碰到一个问题:有一个正整数集合,天天需要把所有数都变成1。 每一次操作,天天可以找一个素数X,让集合中的每一个数都移除(移除等同于除尽)这个素因子(若某数不包含素因子X,则该数不变)。如果这个时候集合内所有数都为1,则结束操作。否则,把集合中所有大于1的数乘以在素数表中排在X之后的那个素数(素数表按从小到大排序,素数表是所有的素数的集合)。天天讨厌麻烦,所以他想知道最少几次操作可以把整个集合中每个数都变成1。 输入多组数据。每组数据有两行,第一行是一个数n(0< n ≤10000)表示集合中有多少个数,如果n为0,表示输入结束,这组样例不需要处理。 第二行是集合中n个数(0< 集合中每个数≤105) 输出每组数据输出一行包括最少的操作次数。 样例输入3 2 3 6 4 1 1 1 1 0 样例输出2 0 线索第一个例子先取x=2,那么集合内每个元素去掉2的因子后为{1,3,3},然后乘以2后面的下一个素数3,新集合为{1,9,9},然后再选x=3,集合变为{1,1,1}。 SourceXTU OnlineJudge |
思路:打出素数表,计算出输入数据中包含的最大素数和最小素数,然后最大素数与最小素数之间的素数的个数加1就是答案了。
#include<stdio.h>
#include<string.h>
const int MAXN=110005;//求出素数要包括大于100000的第一个素数
bool vis[MAXN];
long long prime[MAXN/5];
int tot=0;
void getPrime()
{
for(long long i=2;i<MAXN;i++)
if(!vis[i])
{
prime[tot++]=i;
for(long long j=i*i;j<MAXN;j+=i) vis[j]=true;
}
}
int arr[10005];
int b[100005];
int main(){
int t;
getPrime();
//printf("%d\n",tot);
while(scanf("%d",&t)&&t!=0){
memset(b,0,sizeof(b));
int max=0;//记录最大的素数
int min=MAXN;//记录最小的素数
for(int i=0;i<t;i++) scanf("%d",&arr[i]);
for(int j=0;j<t;j++){
int n=arr[j];
int k=0;
for(int i=0;prime[i]*prime[i]<=n;i++){
if(n%prime[i]==0){
if(prime[i]>max) max=prime[i];
if(prime[i]<min) min=prime[i];
while(n%prime[i]==0){
k++;
n/=prime[i];
}
if(k>b[prime[i]]) b[prime[i]]=k;
}
}
if(n!=1){
b[n]=1;
if(n>max) max=n;
if(n<min) min=n;
}
}
int ans=0;
//for(int i=0;i<1005;i++) ans+=b[i];
int x=0,y=0;
for(int i=0;i<tot;i++){
if(prime[i]==min){
x=i;
}
if(prime[i]==max){
y=i;
//printf("max=%d\n",max);
break;
}
}
if(max==0) ans=0;//对全是1的情况进行特判
else ans=y-x+1;//记算最大素数和最小之间的素数个数加1
printf("%d\n",ans);
}
return 0;
}
原文地址:http://blog.csdn.net/lxpaopao/article/details/46390341