7.14.实验 解题参考

ProblemA(HDU1215)
ProblemB(HDU1286)
这两题是上课例题,不再赘述了。
ProblemC(HDU1406)
【一】这题的数据可以直接判断,在num1和num2之间的数是否符合要求。但有个巨坑需要注意,num1和num2不一定是大小顺序给出的!!
【二】但既然学会了筛选法,很明显可以看到这题先预处理,将10000以内的数据先用判断函数跑一遍,存表再做会有更高的效率。
而且,作为一个解题经验技巧来说,这个完数的条件比较苛刻,也就是所很多很多数里面才能出现很少的数符合条件,而10000也不是特别大。那么抱着好奇的心态我会让跑出来的结果先输出一遍,看看到底有多少个数。
结果当然没有让我失望,只有6,28,496,8128这四个完数!大家都意识到了吧,预处理都可以精简到几乎没有了!不用占用运行的时间咯~

//裸版
#include <stdio.h>
int sum(int n)
{
    int s = 0, i;
    for (i = 1; i <= n/2; i++)
    {
        if(n%i == 0)
            s += i;
    }
    return s;
}
int main()
{
    int n, num1, num2, i, count;
    scanf("%d", &n);
    while(n--)
    {
        scanf("%d%d", &num1, &num2);
        count = 0;
        if(num1 > num2)
        {
            int t=num1;
            num1=num2;
            num2=t;
        }
        for (i = num1; i <= num2; i++)
        {
            if(i == sum(i))
                count++;
        }
        printf("%d\n", count);
    }
    return 0;
}
//精装版
#include <stdio.h>
int main()
{
    int n,a,b,i,count;
    int pn[4]={6,28,496,8128};
    scanf("%d",&n);
    while(n--)
    {
        count=0;
        scanf("%d %d",&a,&b);
        if(a>b) a^=b^=a^=b;//炫个技,我见过的交换两个数的最短代码...
        for(i=0;i<4;i++)
            if(a<=pn[i]&&pn[i]<=b)
                count++;
        printf("%d\n",count);
    }
    return 0;
}

ProblemD(HDU4548)
典型的筛法求素数,打表预处理。
先用筛法筛出数据范围内的素数,再将每个数以内有多少个素数递推求出来存在表primeNums里。之后求a和b直接就可以直接用primeNums[b]-primeNums[a]。
这个算法非常有效率。求primeNums表其实是对需求的一个预处理,而这个预处理前面需要用到的素数表其实又是一个叠加的预处理。

#include <stdio.h>
#include <string.h>

const int MAX_N = 1000001;
bool isPrime(int n)
{
  if (n == 2) return true;
  for (int r = 2; r * r <= n; r++)
  {
    if (n % r == 0) return false;
  }
  return true;
}

bool isMeiPrime(int n)
{
  int d = 0;
  while (n)
  {
    d += n % 10;
    n /= 10;
  }
  return isPrime(d);
}

int primeNums[MAX_N];
bool primes[MAX_N];

void seive()
{
  memset(primes, 0, MAX_N * sizeof(bool));
  for (int i = 2; i < MAX_N; i++)
  {
    if (!primes[i])
    {
      for (int j = i << 1; j < MAX_N; j += i)
      {
        primes[j] = true;
      }
    }
  }

  primeNums[0] = 0, primeNums[1] = 0;
  for (int i = 2; i < MAX_N; i++)
  {
    if (!primes[i] && isMeiPrime(i)) primeNums[i] = primeNums[i-1] + 1;
    else primeNums[i] = primeNums[i-1];
  }
}

int main()
{
  seive();
  int T, a, b;
  scanf("%d", &T);
  for (int t = 1; t <= T; t++)
  {
    scanf("%d %d", &a, &b);
    printf("Case #%d: %d\n", t, primeNums[b] - primeNums[a-1]);
  }
  return 0;
}

ProblemE(HDU1164)
将一个数分解为几个素数相乘的形式。看数据量很容易想到先预处理,用筛法得到素数表。之后慢慢分解输入的数,遇到能整除的素数就输入,并让其不断缩小即可。

#include <iostream>
#include <cmath>
#include <stdio.h>
#include <string.h>
using namespace std;

bool brr[65536];
int arr[7001];

void FindPrime(void)
{
    int i,j,k;
    memset(brr,1,sizeof(brr));
    k=0;
    for(i=2;i<65536;++i)
        if(brr[i])
        {
            for(j=i+i;j<65536;j+=i)
                brr[j]=0;
            arr[k]=i;
            ++k;
        }
}

int main()
{
    int x,i;
    FindPrime();
    while(scanf("%d",&x)!=EOF)
    {
        for(i=0;i<=x && !brr[x];++i)
            if(x%arr[i]==0)
            {
                printf("%d*",arr[i]);
                x/=arr[i];
                --i;
            }
        printf("%d\n",x);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章