XTU 1183 Factors

来源:互联网 发布:mysql 存储过程 性能 编辑:程序博客网 时间:2024/06/07 20:17

Factors

Accepted : 9 Submit : 65Time 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

输出

每组数据输出一行包括最少的操作次数。

样例输入

32 3 641 1 1 10

样例输出

20

线索

第一个例子先取x=2,那么集合内每个元素去掉2的因子后为{1,3,3},然后乘以2后面的下一个素数3,新集合为{1,9,9},然后再选x=3,集合变为{1,1,1}。


Source

XTU 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;//记算最大素数和最小之间的素数个数加1printf("%d\n",ans);}return 0;}


0 0