ural 2003. Simple Magic 数论 因数分解

2003. Simple Magic

Time limit: 1.0 second
Memory limit: 64 MB
Do you think that magic is simple? That some hand-waving and muttering incomprehensible blubber is enough to conjure wonderful gardens or a fireball to burn your enemies to ashes?
The reality is a little more complicated than that. To master skills, young wizards spend years studying such subjects as magical analysis and demonology practice.
In fact, Oleg, a student of the Institute of Magic and Common Sorcery (IMCS) is preparing for an exam. And there’s no way he can calculate the Dumbledore determinant. As you might have guessed, he asked you to help him.
Let us remind you the basic definitions just in case you haven’t been visiting lectures on the theory of nonlinear spells. The Gandalf theorem states that any part of subspace can be represented as a vector of magic potentials that is an array of  n positive integers. A Dumbledore determinant of this array equals the minimum number of elementary magical transformations required to turn the original array into the array where all elements are equal to one. One elementary magical transformation turns the original array of length  k into a new array of length  k · ( k − 1) / 2. The elements of the new array are greatest common divisors of each pair of elements of the original array. For example, the elementary magical transformation of array {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}.

Input

The first line contains number  n that is the length of the original array (3 ≤  n ≤ 10 000). Next  nlines contain the elements of array that are positive integers not exceeding 10 7.

Output

Output Dumbledore determinant for the array given in the input. If Dumbledore determinant is not defined or it exceeds 10 18, output “infinity”.

Samples

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;
}






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值