input | output |
---|---|
3 1 2 3 |
1 |
4 2 2 2 2 |
infinity |
这题没加根号的优化会T, 别问我是怎么知道的
题意:就是一列数字, 像他给的样例一样操作
{2, 3, 3, 6} turns it into array {gcd(2, 3), gcd(2, 3), gcd(2, 6), gcd(3, 3), gcd(3, 6), gcd(3, 6)}, that is {1, 1, 2, 3, 3, 3}.
然后问,不断这要操作,几遍可以得到都是1的数组。
做法: 暴力打个表发现 要么 只用1次 要么两次 要么 就是无穷的。
因为n很大,操作一次就要超时的。所以要在原始数组中想方法判断。
开始,我是通过暴力打表发现的,如果任何两个数都互质,那么只用一次就可以变成1。只要有两个数不互质,那么 就要2次才能都变1。 如果有三个数或以上 两两不互质 那么就要无穷次,不断循环下去了。
yy一下,发现这结论也是对的。 两个数不互质,一轮之后就变成只有非1 的数,再一轮 就全是1了。 如果有三个数以上两两不互质,那么他必然会再产生三个以上两两不互质的数,就无限循环下去,不会有都是1的情况出现了。
知道了结论,要想做法了。
找有没有三个数两两不互质,得for三层,是 肯定要超时的。 然后问了同学。。 只要因数分解就可以了。 分解的时候要注意, 比如8 可以分解为2*2*2, 但是8是一个数,所以算2这个素数个数的时候是只加1的。 然后判断最大的素数个数是多少。大于等于3,是无限,等于2是两次,等于1是一次,等于0 说明全是1,就是0次;
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> #include <malloc.h> #include <ctype.h> #include <math.h> #include <string> #include <iostream> #include <algorithm> using namespace std; #include <stack> #include <queue> #include <vector> #include <deque> #include <set> #include <map> #define INF 999999999 #define eps 0.00001 #define LL __int64d #define pi acos(-1.0) #define ll int //只能int 不然数组存不下 #define N 10000020 //prime[0,primenum) ll prime[1000000], primenum; bool Isprime[N+10]; //<=Max_Prime的素数 void PRIME(ll Max_Prime){ primenum = 0; Isprime[0] = Isprime[1] = 0; Isprime[2] = 1; prime[primenum++] = 2; for(ll i = 3; i <= Max_Prime; i++) Isprime[i] = i&1; for (ll i = 3; i <= Max_Prime; i+=2){ if(Isprime[i]) prime[primenum++] = i; for (ll j = 0; j < primenum; j++){ if(prime[j] * i > Max_Prime)break; Isprime[prime[j]*i] = 0; if(i%prime[j] == 0)break; } } } int gcd(int n,int m){//最大公因数 if(n<m) swap(n,m); int tmp; while(m){tmp=n;n=m;m=tmp%m;} return n; } int lcm(int n,int m){//最小公倍数 return n*(m/gcd(n,m));//预防 m*n 超过整形,先除一下。 } int flag; int has[10000010]; void add(int x) { int tem=sqrt(1.0*x); for(int i=0;i<primenum&&prime[i]<=tem&&x!=1;i++) { if(x%prime[i]==0) { x/=prime[i]; has[prime[i]]++; } while(x%prime[i]==0) x/=prime[i]; } if(x!=1) has[x]++; } void cal() { for(int i=0;i<primenum;i++) { if(has[prime[i]]==2&&flag<2) flag=2; else if(has[prime[i]]>=3) flag=3; } } int a[10010]; int main() { PRIME(10000002); int n; while(scanf("%d",&n)!=EOF) { memset(has,0,sizeof has); flag=0; for(int i=0;i<n;i++) { scanf("%d",&a[i]); add(a[i]); if(a[i]!=1) flag=1; } cal(); if(flag==3) puts("infinity"); else printf("%d\n",flag); } return 0; }