Atcoder2004:Anticube(质因数分解,思维)

Snuke got positive integers s1,…,sN from his mother, as a birthday present. There may be duplicate elements.

He will circle some of these N integers. Since he dislikes cubic numbers, he wants to ensure that if both si and sj(i≠j) are circled, the product sisj is not cubic. For example, when s1=1,s2=1,s3=2,s4=4, it is not possible to circle both s1 and s2 at the same time. It is not possible to circle both s3 and s4 at the same time, either.

Find the maximum number of integers that Snuke can circle.

Constraints
1≦N≦105
1≦si≦1010
All input values are integers.
Input
The input is given from Standard Input in the following format:

N
s1
:
sN
Output
Print the maximum number of integers that Snuke can circle.

Sample Input 1
8
1
2
3
4
5
6
7
8
Sample Output 1
6
Snuke can circle 1,2,3,5,6,7.

Sample Input 2
6
2
4
8
16
32
64
Sample Output 2
3
Sample Input 3
10
1
10
100
1000000007
10000000000
1000000009
999999999
999
999
999
Sample Output 3
9
题意:给出一个长度为n的数列,在里面找出一些数,使得任意两个数ai,aj相乘不是立方数。
题解:这题要两个数相乘不是立方数,那我们就用质因数分解了,分解质因数后把所有的质因子模3,然后可以得出它和它得补数(如3的1次方的补数是3的2次方,5的2次方补数是5的1次方),它和它得补数是一一对应得,所以我们在它和它得补数之间取出现次数最多得,但是这个题对100000个数求质因子会有几个案例会超时,因为这个题是立方,所以我们只有判断sqrt3(1e10)个数的质因子打表,对于大于sqrt3(1e10)的,只有判断一下它是不是完全平方数,不是完全平方数的话,因为它的质因子都大于sqrt3(1e10)了,所以它的补数肯定会大于1e10,那么它就可以随便选啦。
AC代码

#include
#define ll long long
using namespace std;
ll p[2200],a[100005],k[100005];
int cnt=0;
mapx;
mapvis;
ll M(ll t,ll h)
{
    ll ans1=1,ans2=1;
    for(int i=0;i1e10) ans2=0;
            ans2*=p[i];
        }
        else ans1*=p[i]*p[i],ans2*=p[i];
        if(ans2>1e10) ans2=0;
    }
    ans1*=t;
    ll w=(ll)sqrt(t);
    if(w*w==t)
        ans2*=w;
    else
    {
        ans2*=t;
        if(ans2>1e10) ans2=0;
        ans2*=t;
    }
    if(ans2>1e10) ans2=0;
    x[ans1]++;
    k[h]=ans2;
    return ans1;
}
int main()
{
    for(int i=2;i<=2200;i++)
    {
        bool flag=true;
        for(int j=2;j*j<=i;j++)
        if(i%j==0) {flag=false;break;}
        if(flag) p[cnt++]=i;
    }
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        ll m;
        scanf("%lld",&m);
        a[i]=M(m,i);
    }
    int ans=0;
    vis[1]=true;
    for(int i=1;i<=n;i++)
        if(!vis[a[i]]) ans+=max(x[a[i]],x[k[i]]),vis[a[i]]=vis[k[i]]=true;
    if(x[1]>=1) ans++;
    printf("%d\n",ans);
}

你可能感兴趣的:(算法)