打表

来源:互联网 发布:googlenet网络结构图 编辑:程序博客网 时间:2024/06/11 16:06
作为一名ACM新手,每一天上课的收获都是很令人开心的,今天第一个收获就是打表,首先是打素数表,也就是素数筛法。就拿求1到100之内的素数为例,我们先开一个大小比上限稍大的一维数组val[i]来表示“i”这个数的状态,并将数组全部初始化为状态1,然后我们知道2是最小的素数,那么我们就把所有小于100000且为2的倍数的状态改为0,然后进入循环i++,如果val[i]=1;则将它所有倍数标记为状态0,如果val[i]=0就跳过,直到i=100为止。然后我们再用一个数组来存储素数,枚举val[i],如果为状态1,就放进数组,如果状态为0,就逃过。然后我们就得到了一个装有1到100的素数的按升序排序的数组。这时你可以用来判断一个数是不是素数,也可以直接输出。在ACM里面,直接打表一般来说对于多组问题时间复杂度要低一些。实现代码如下:
int val[110],p[110],cnt=0;void init(){    for(int i=2;i<=100;i++)    val[i]=1;    for(int i=2;i<=100;i++)    {        if(val[i])        {            for(int j=i+i;j<=100;j+=i)            {                val[j]=0;            }        }    }    for(int i=2;i<=100;i++)    {        if(val[i]==1)            p[cnt++]=i;    }}

同样的,我们可以打出欧拉函数的表,在数论,对正整数n,欧拉函数是小于等于n的数中与n互质的数的数目, 例如φ(8)=4,因为1,3,5,7均和8互质。欧拉筛法与素数筛法几乎一样,都是找到一个最小的质数,然后对后面的倍数进行求解。由于φ(n)=n∏(pi-1)/pi,所以有phi[i]=phi[i]/i*(i-1);下面贴一份樊老师讲的代码。

int phi[11000];void phi_table(int n){    for(int i=2;i<=n;i++)phi[i]=0;    phi[1]=1;    for(int i=2;i<=n;i++)    {        if(!phi[i])            for(int j=i;j<=n;j+=i)//注意,素数筛法这里j初始为2*i,此处为i;        {            if(!phi[j])phi[j]=j;            phi[j]=phi[j]/i*(i-1);        }    }}




1 0