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; }
时间: 2024-10-20 04:16:43