SDUT 3257 Cube Number 素数筛的应用加强版 立方数的性质

来源:互联网 发布:作品集网站 知乎 编辑:程序博客网 时间:2024/04/30 20:32

题意: 给n个数然后让你从中挑出两个数,使这俩个数相乘为一个立方数,求n个数中有多少对。

思路:首先分析立方数的性质,立方数的构成性质。

 n^3=a^3*b^3*c^3....  //最小单位划分

其中a,b,c..都为素数或者 是1

然后再来看x*y=n^3 的性质,

x=a^3*b^3...*d^2*e;

y=a^3*b^3....*d*e^2;

 

所以求个数,只需要枚举统计出每个数中不可以构成立方的那部分,

现将所有的数去掉三次方的约数,只需要找出与剩余部分相匹配的数的个数即可。


///时间是 1s 多   ,下面有优化的代码。

#include <cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<map>#include<cmath>#include<cstdlib>#define LL long long#define bug puts("***********")#define INF 0x3f3f3f3fusing namespace std;int a;bool vis[1000100];LL primer[10000];int num=0;void init(){    int m=100;    memset(vis,true,sizeof(vis));    for(int i=2;i<=m;i++)    {        if(vis[i])        for(int j=i*i;j<=10001;j+=i)        {            vis[j]=false;        }    }    vis[0]=false;    vis[1]=false;    for(int i=0;i<=10001;i++)    {        if(vis[i])            primer[num++]=i;    }}int main(){    int t;    init();    scanf("%d",&t);    while(t--)    {        map<LL,int>tongji;        int n;        scanf("%d",&n);        LL sum=0;        for(int i=0;i<n;i++)        {            scanf("%lld",&a);            LL now=1;          ///表示当前数去掉三次方之后的得到的数            LL need=1;         ///表示需要与now匹配的数(即now*need为立方数)            for(int j=0;j<num;j++)            {                while(a%(primer[j]*primer[j]*primer[j])==0)  ///简化去三次方                {                    a/=(primer[j]*primer[j]*primer[j]);                }                if(a%(primer[j]*primer[j])==0)         ///  找到存在二次方的数                {                    a/=(primer[j]*primer[j]);                    now=now*primer[j]*primer[j];                          need=need*primer[j];                               }                if(a<primer[j]*primer[j]) break;            }            now=now*a;            need=need*a*a;            sum=sum+(LL)tongji[need];            tongji[now]++;        }        printf("%lld\n",sum);    }    return 0;}
//优化。。 时间700ms
#include <cstdio>#include<cstring>#include<iostream>#include<algorithm>#include<map>#include<cmath>#include<cstdlib>#define LL long long#define bug puts("***********")#define INF 0x3f3f3f3fusing namespace std;int a;bool vis[1000100];LL primer[10000];int num=0;int tongji[1001000];void init(){    int m=100;    memset(vis,true,sizeof(vis));    for(int i=2;i<=m;i++)    {        if(vis[i])        for(int j=i*i;j<=10001;j+=i)        {            vis[j]=false;        }    }    vis[0]=false;    vis[1]=false;    for(int i=0;i<=10001;i++)    {        if(vis[i])            primer[num++]=i;    }}int main(){    int t;    init();    scanf("%d",&t);    while(t--)    {        memset(tongji,0,sizeof(tongji));        int n;        scanf("%d",&n);        LL sum=0;        for(int i=0;i<n;i++)        {            scanf("%d",&a);            LL now=1;            LL need=1;            for(int j=0;j<num;j++)            {               int geshu=0;                while(a%(primer[j])==0)      ///这样比上一个快                {                    a/=primer[j];                    geshu++;                }                                if(geshu%3==2)                {                    now=now*primer[j]*primer[j];                    need=need*primer[j];                }                else if(geshu%3==1)                    a=a*primer[j];                                    if(need>1000000)                    ///因为now一定是小于1000000 所以没必要统计tongji[]下标大于1000000,                {                    break;                }                if(a<primer[j]*primer[j]) break;            }            if(need<=1000000&&need>0)            {              now=now*a;              need=need*a*a;              if(need>1000000)               continue;              sum=sum+(LL)tongji[need];            ///need>1000000  tongji[need]一定等于0              tongji[now]++;            }        }        printf("%lld\n",sum);    }    return 0;}


1 0
原创粉丝点击